11# json-serialization
2- # Copyright (c) 2019-2023 Status Research & Development GmbH
2+ # Copyright (c) 2019-2025 Status Research & Development GmbH
33# Licensed under either of
44# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
55# * MIT license ([LICENSE-MIT](LICENSE-MIT))
66# at your option.
77# This file may not be copied, modified, or distributed except according to
88# those terms.
99
10+ {.push gcsafe , raises : [].}
11+
1012import
1113 std/ [json, typetraits],
1214 faststreams/ [outputs, textio],
@@ -40,9 +42,7 @@ func init*(W: type JsonWriter, stream: OutputStream,
4042 nestingLevel: if pretty: 0 else : - 1 ,
4143 state: RecordExpected )
4244
43- proc beginRecord * (w: var JsonWriter , T: type )
44- proc beginRecord * (w: var JsonWriter )
45- proc writeValue * (w: var JsonWriter , value: auto ) {.gcsafe , raises : [IOError ].}
45+ proc writeValue * (w: var JsonWriter , value: auto ) {.raises : [IOError ].}
4646
4747# If it's an optional field, test for it's value before write something.
4848# If it's non optional field, the field is always written.
@@ -58,7 +58,7 @@ template indent =
5858template `$` * (s: JsonString ): string =
5959 string (s)
6060
61- proc writeFieldName * (w: var JsonWriter , name: string ) =
61+ proc writeFieldName * (w: var JsonWriter , name: string ) {. raises : [ IOError ].} =
6262 # this is implemented as a separate proc in order to
6363 # keep the code bloat from `writeField` to a minimum
6464 doAssert w.state != RecordExpected
@@ -101,7 +101,7 @@ proc writeField*(
101101template fieldWritten * (w: var JsonWriter ) =
102102 w.state = AfterField
103103
104- proc beginRecord * (w: var JsonWriter ) =
104+ proc beginRecord * (w: var JsonWriter ) {. raises : [ IOError ].} =
105105 doAssert w.state == RecordExpected
106106
107107 append '{'
@@ -110,11 +110,11 @@ proc beginRecord*(w: var JsonWriter) =
110110
111111 w.state = RecordStarted
112112
113- proc beginRecord * (w: var JsonWriter , T: type ) =
113+ proc beginRecord * (w: var JsonWriter , T: type ) {. raises : [ IOError ].} =
114114 w.beginRecord ()
115115 if w.hasTypeAnnotations: w.writeField (" $type" , typetraits.name (T))
116116
117- proc endRecord * (w: var JsonWriter ) =
117+ proc endRecord * (w: var JsonWriter ) {. raises : [ IOError ].} =
118118 doAssert w.state != RecordExpected
119119
120120 if w.hasPrettyOutput:
@@ -128,7 +128,7 @@ template endRecordField*(w: var JsonWriter) =
128128 endRecord (w)
129129 w.state = AfterField
130130
131- iterator stepwiseArrayCreation * [C](w: var JsonWriter , collection: C): auto =
131+ iterator stepwiseArrayCreation * [C](w: var JsonWriter , collection: C): auto {. raises : [ IOError ].} =
132132 append '['
133133
134134 if w.hasPrettyOutput:
@@ -155,12 +155,12 @@ iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto =
155155
156156 append ']'
157157
158- proc writeIterable * (w: var JsonWriter , collection: auto ) =
158+ proc writeIterable * (w: var JsonWriter , collection: auto ) {. raises : [ IOError ].} =
159159 mixin writeValue
160160 for e in w.stepwiseArrayCreation (collection):
161161 w.writeValue (e)
162162
163- proc writeArray * [T](w: var JsonWriter , elements: openArray [T]) =
163+ proc writeArray * [T](w: var JsonWriter , elements: openArray [T]) {. raises : [ IOError ].} =
164164 writeIterable (w, elements)
165165
166166template writeObject * (w: var JsonWriter , T: type , body: untyped ) =
@@ -193,8 +193,7 @@ template writeObjectField*[FieldType, RecordType](w: var JsonWriter,
193193 type R = type record
194194 w.writeFieldIMPL (FieldTag [R, fieldName], field, record)
195195
196- proc writeRecordValue * (w: var JsonWriter , value: auto )
197- {.gcsafe , raises : [IOError ].} =
196+ proc writeRecordValue * (w: var JsonWriter , value: auto ) {.raises : [IOError ].} =
198197 mixin enumInstanceSerializedFields, writeObjectField
199198 mixin flavorOmitsOptionalFields, shouldWriteObjectField
200199
@@ -216,7 +215,7 @@ proc writeRecordValue*(w: var JsonWriter, value: auto)
216215 discard fieldName
217216 w.endRecord ()
218217
219- proc writeNumber * [F,T](w: var JsonWriter [F], value: JsonNumber [T]) =
218+ proc writeNumber * [F,T](w: var JsonWriter [F], value: JsonNumber [T]) {. raises : [ IOError ].} =
220219 if value.sign == JsonSign .Neg :
221220 append '-'
222221
@@ -246,7 +245,7 @@ proc writeNumber*[F,T](w: var JsonWriter[F], value: JsonNumber[T]) =
246245 else :
247246 append value.exponent
248247
249- proc writeJsonValueRef * [F,T](w: var JsonWriter [F], value: JsonValueRef [T]) =
248+ proc writeJsonValueRef * [F,T](w: var JsonWriter [F], value: JsonValueRef [T]) {. raises : [ IOError ].} =
250249 if value.isNil:
251250 append " null"
252251 return
@@ -289,7 +288,7 @@ template writeValue*(w: var JsonWriter, value: enum) =
289288 type Flavor = type (w).Flavor
290289 writeEnumImpl (w, value, Flavor .flavorEnumRep ())
291290
292- proc writeValue * (w: var JsonWriter , value: auto ) {.gcsafe , raises : [IOError ].} =
291+ proc writeValue * (w: var JsonWriter , value: auto ) {.raises : [IOError ].} =
293292 mixin writeValue
294293
295294 when value is JsonNode :
@@ -391,13 +390,16 @@ proc writeValue*(w: var JsonWriter, value: auto) {.gcsafe, raises: [IOError].} =
391390 const typeName = typetraits.name (value.type )
392391 {.fatal : " Failed to convert to JSON an unsupported type: " & typeName.}
393392
394- proc toJson * (v: auto , pretty = false , typeAnnotations = false ): string =
393+ proc toJson * (v: auto , pretty = false , typeAnnotations = false , Flavor = DefaultFlavor ): string {. raises : [].} =
395394 mixin writeValue
396395
397396 var
398397 s = memoryOutput ()
399- w = JsonWriter [DefaultFlavor ].init (s, pretty, typeAnnotations)
400- w.writeValue v
398+ w = JsonWriter [Flavor ].init (s, pretty, typeAnnotations)
399+ try :
400+ w.writeValue v
401+ except IOError :
402+ raiseAssert " no exceptions from memoryOutput"
401403 s.getOutput (string )
402404
403405template serializesAsTextInJson * (T: type [enum ]) =
0 commit comments