diff --git a/json_serialization/format.nim b/json_serialization/format.nim index 9270dbd..ac31f20 100644 --- a/json_serialization/format.nim +++ b/json_serialization/format.nim @@ -106,7 +106,8 @@ template createJsonFlavor*(FlavorName: untyped, requireAllFields = true, omitOptionalFields = true, allowUnknownFields = true, - skipNullFields = false) {.dirty.} = + skipNullFields = false, + automaticPrimitivesSerialization = true) {.dirty.} = when declared(SerializationFormat): # Earlier versions lack mimeTypeValue createFlavor(Json, FlavorName, mimeTypeValue) else: @@ -137,5 +138,4 @@ template createJsonFlavor*(FlavorName: untyped, # Set default to true for backward compatibility # but user can call it again later with different value. # Or fine tuning use `Flavor.automaticSerialization(type, true/false)` - FlavorName.automaticBuiltinSerialization(true) - + FlavorName.automaticBuiltinSerialization(automaticPrimitivesSerialization) diff --git a/json_serialization/reader_impl.nim b/json_serialization/reader_impl.nim index e4a017a..003917d 100644 --- a/json_serialization/reader_impl.nim +++ b/json_serialization/reader_impl.nim @@ -225,22 +225,66 @@ proc readRecordValue*[T](r: var JsonReader, value: var T) else: r.raiseUnexpectedField(key, cstring typeName) -template autoSerializeCheck(F: distinct type, T: distinct type) = +template autoSerializeCheck(F: distinct type, T: distinct type, body) = when declared(macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey mixin typeAutoSerialize when not F.typeAutoSerialize(T): - const typeName = typetraits.name(T) - {.error: "automatic serialization is not enabled or readValue not implemented for `" & + const + typeName = typetraits.name(T) + flavorName = typetraits.name(F) + {.error: flavorName & + ": automatic serialization is not enabled or readValue not implemented for `" & typeName & "`".} + else: + body + else: + body -template autoSerializeCheck(F: distinct type, TC: distinct type, M: distinct type) = +template autoSerializeCheck(F: distinct type, TC: distinct type, M: distinct type, body) = when declared(macrocache.hasKey): # Nim 1.6 have no macrocache.hasKey mixin typeClassOrMemberAutoSerialize when not F.typeClassOrMemberAutoSerialize(TC, M): - const typeName = typetraits.name(M) - const typeClassName = typetraits.name(TC) - {.error: "automatic serialization is not enabled or readValue not implemented for `" & + const + typeName = typetraits.name(M) + typeClassName = typetraits.name(TC) + flavorName = typetraits.name(F) + {.error: flavorName & + ": automatic serialization is not enabled or readValue not implemented for `" & typeName & "` of typeclass `" & typeClassName & "`".} + else: + body + else: + body + +template readValueRefOrPtr(r, value) = + mixin readValue + when compiles(isNotNilCheck(value)): + allocPtr value + value[] = readValue(r, type(value[])) + else: + if r.tokKind == JsonValueKind.Null: + value = nil + r.parseNull() + else: + allocPtr value + value[] = readValue(r, type(value[])) + +template readValueObjectOrTuple(Flavor, r, value) = + mixin flavorUsesAutomaticObjectSerialization + + const isAutomatic = + flavorUsesAutomaticObjectSerialization(Flavor) + + when not isAutomatic: + const + flavor = + "JsonReader[" & typetraits.name(typeof(r).Flavor) & "], " & + typetraits.name(T) + {.error: + "Missing Json serialization import or implementation for readValue(" & + flavor & ")".} + + readRecordValue(r, value) proc readValue*[T](r: var JsonReader, value: var T) {.raises: [SerializationError, IOError].} = @@ -261,129 +305,110 @@ proc readValue*[T](r: var JsonReader, value: var T) type Flavor = JsonReader.Flavor when value is JsonString: - autoSerializeCheck(Flavor, JsonString) - value = r.parseAsString() + autoSerializeCheck(Flavor, JsonString): + value = r.parseAsString() elif value is JsonNode: - autoSerializeCheck(Flavor, JsonNode) - value = r.parseJsonNode() + autoSerializeCheck(Flavor, JsonNode): + value = r.parseJsonNode() elif value is JsonNumber: - autoSerializeCheck(Flavor, JsonNumber) - r.parseNumber(value) + autoSerializeCheck(Flavor, JsonNumber): + r.parseNumber(value) elif value is JsonVoid: - autoSerializeCheck(Flavor, JsonVoid) - r.skipSingleJsValue() + autoSerializeCheck(Flavor, JsonVoid): + r.skipSingleJsValue() elif value is JsonValueRef: - autoSerializeCheck(Flavor, JsonValueRef) - r.parseValue(value) + autoSerializeCheck(Flavor, JsonValueRef): + r.parseValue(value) elif value is string: - autoSerializeCheck(Flavor, string) - value = r.parseString() + autoSerializeCheck(Flavor, string): + value = r.parseString() elif value is seq[char]: - autoSerializeCheck(Flavor, seq[char]) - let val = r.parseString() - value.setLen(val.len) - for i in 0..