json.net - JsonConverters and object properties -


i'm trying find answer problem has stumped me few days, i'm converting legacy wcf code on signalr, it's internal api , client silverlight moment.

i have .net class (content1) on server side has matching json converter , message class (message1) has property of type content1. seems work fine, problem when property changed type object (which current code is)

public class message1 {     public string name { get; set; }      public object payload { get; set; } } 

now custom jsonconverter no longer called.

i've placed converter in jsonserializer.converters collection , can see canconvert method being hit on converter, property comes through request convert system.object.

i've enabled typenamehandling , set auto (all/object/array not option signalr breaks), , can see $type property being written json

{   "name": "test message 1",   "payload": {     "$type": "models.content1, models, version=1.0.0.0, culture=neutral, publickeytoken=0d90b1aaa82178d3",     "propert1": "this string"   } } 

and tracing turned on can see type being resolved

resolved type 'models.content1, models, version=1.0.0.0, culture=neutral, publickeytoken=0d90b1aaa82178d3to models.content1. path 'payload.$type'.

but custom converter never called.

so crux of issue is, there way json.net delegate class level custom converter when using $type?

or failing that, if write custom converter , register object property

public class message1 {     public string name { get; set; }      [jsonconverter(typeof(yetanotherconverter))]     public object payload { get; set; } } 

is there way peek ahead @ type of object via $type property, i'd this

public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)     {         var data = jobject.load(reader);         var type = data.property("$type");         if (type.value.value<string>().contains("content1"))         {             var obj = serializer.deserialize<content1>(reader);             return obj;         }         if (type.value.value<string>().contains("content2"))         {             var obj = serializer.deserialize<content2>(reader);             return obj;         }          return serializer.deserialize(reader);     } 

which invoke correct jsonconverters type, in reality not work jsonreader forward can't 'peek' @ type.

i suppose go route of making json serialise more below

{   "name": "test message 1",   "payload": {     "$type": "models.content1, models, version=1.0.0.0, culture=neutral, publickeytoken=0d90b1aaa82178d3",     "data": {       "propert1": "this string"     }   } } 

then can edge forward through json reader, $type (should use different name @ point i've mangled in original use), find data section , pass off serialiser correct object type invoke converter in class level attribute.

but feels i'm heading of down rabbit hole deep, can't right!

thanks

stephen.

looks converter polymorphic type not called in case.

what can instead create yetanotherconverter; in readjson load object jtoken, parse "$type" property, call jtoken.toobject(type, serializer) deserialize intermediate jtoken final type. ensures converter gets called. thus:

public class polymorphicconverter : jsonconverter {     public override bool canconvert(type objecttype)     {         return objecttype == typeof(object);     }      public override bool canwrite { { return false; } }      public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)     {         var token = jtoken.load(reader);         if (token.type != jtokentype.object)             return token;         var typestring = (string)token["$type"];         if (typestring == null)             return token;         string typename, assemblyname;         splitfullyqualifiedtypename(typestring, out typename, out assemblyname);         var type = serializer.binder.bindtotype(assemblyname, typename);         if (type != null)             return token.toobject(type, serializer);         return token;     }      public override void writejson(jsonwriter writer, object value, jsonserializer serializer)     {         throw new notimplementedexception();     }      // utilities taken https://github.com/jamesnk/newtonsoft.json/blob/master/src/newtonsoft.json/utilities/reflectionutils.cs     // couldn't find way access these directly.      public static void splitfullyqualifiedtypename(string fullyqualifiedtypename, out string typename, out string assemblyname)     {         int? assemblydelimiterindex = getassemblydelimiterindex(fullyqualifiedtypename);          if (assemblydelimiterindex != null)         {             typename = fullyqualifiedtypename.substring(0, assemblydelimiterindex.value).trim();             assemblyname = fullyqualifiedtypename.substring(assemblydelimiterindex.value + 1, fullyqualifiedtypename.length - assemblydelimiterindex.value - 1).trim();         }         else         {             typename = fullyqualifiedtypename;             assemblyname = null;         }     }      private static int? getassemblydelimiterindex(string fullyqualifiedtypename)     {         int scope = 0;         (int = 0; < fullyqualifiedtypename.length; i++)         {             char current = fullyqualifiedtypename[i];             switch (current)             {                 case '[':                     scope++;                     break;                 case ']':                     scope--;                     break;                 case ',':                     if (scope == 0)                         return i;                     break;             }         }          return null;     } } 

and then:

public class message1 {     public string name { get; set; }      [jsonconverter(typeof(polymorphicconverter))]     public object payload { get; set; } } 

Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -