c# - Recursively call JsonSerializer in a JsonConverter -
i'm writing jsonconverter
perform conversion tasks need accomplished on read/write. in particular, i'm taking existing serialization behavior , tacking on additional properties on write / reading additional properties on read.
inside jsonconverter
, i'd make use of passed jsonserializer
instance perform majority of conversion functionality. however, when this, end in recursive loop serializer calls converter calls serializer calls converter , etc.
i've seen people things such use jsonconvert.serializeobject
, passing in converters serializer instance except this
. however, won't work me because bypasses of other customization i've done on serializer, such custom contract resolver , datetime
handling.
is there way can either:
- use serializer instance passed me, somehow exclude converter, or
- clone serializer passed me (without manually constructing new 1 , copying property property) , remove converter?
this common problem. using "jsonconvert.serializeobject" isn't bad idea. however, 1 trick can used in circumstances (typically collections) cast interface when writing , deserialize simple derivative when reading.
below simple converter deals dictionaries might have been serialized set of kvps rather looking object (showing age here :) )
note "writejson" casts idictionary< k,v> , "readjson" uses "dummydictionary". end right thing uses passed serializer without causing recursion.
/// <summary> /// converts <see cref="keyvaluepair{tkey,tvalue}"/> , json. /// </summary> public class dictionaryaskvpconverter<tkey, tvalue> : jsonconverter { /// <summary> /// determines whether instance can convert specified object type. /// </summary> /// <param name="objecttype">type of object.</param> /// <returns> /// <c>true</c> if instance can convert specified object type; otherwise, <c>false</c>. /// </returns> public override bool canconvert(type objecttype) { if (!objecttype.isvaluetype && objecttype.isgenerictype) return (objecttype.getgenerictypedefinition() == typeof(dictionary<,>)); return false; } /// <summary> /// writes json representation of object. /// </summary> /// <param name="writer">the <see cref="jsonwriter"/> write to.</param> /// <param name="value">the value.</param> /// <param name="serializer">the calling serializer.</param> public override void writejson(jsonwriter writer, object value, jsonserializer serializer) { var dictionary = value idictionary<tkey, tvalue>; serializer.serialize(writer, dictionary); } /// <summary> /// reads json representation of object. /// </summary> /// <param name="reader">the <see cref="jsonreader"/> read from.</param> /// <param name="objecttype">type of object.</param> /// <param name="existingvalue">the existing value of object being read.</param> /// <param name="serializer">the calling serializer.</param> /// <returns>the object value.</returns> public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer) { dictionary<tkey, tvalue> dictionary; if (reader.tokentype == jsontoken.startarray) { dictionary = new dictionary<tkey, tvalue>(); reader.read(); while (reader.tokentype == jsontoken.startobject) { var kvp = serializer.deserialize<keyvaluepair<tkey, tvalue>>(reader); dictionary[kvp.key] = kvp.value; reader.read(); } } else if (reader.tokentype == jsontoken.startobject) // use dummydictionary fool jsonserializer not using converter recursively dictionary = serializer.deserialize<dummydictionary>(reader); else dictionary = new dictionary<tkey, tvalue>(); return dictionary; } /// <summary> /// dummy fool jsonserializer not using converter recursively /// </summary> private class dummydictionary : dictionary<tkey, tvalue> { } }
Comments
Post a Comment