c# - id field resolution when using JObject.FromObject -


i have family of custom json converters. work this:

public override void writejson(newtonsoft.json.jsonwriter writer, object value, newtonsoft.json.jsonserializer serializer) {   jobject jo = jobject.fromobject(value);   // own stuff jobject here -- adding property. value of property depends on specific converter being used.   jo.writeto(writer, this); } 

the problem id field of jobject 1. not good. tried using inner serializer id field:

private jsonserializer _innerserializer {get;set;} private jsonserializer innerserializer {   {     if (_innerserializer == null) {       _innerserializer = new jsonserializer();     }     return _innerserializer;   } }  public override void writejson(newtonsoft.json.jsonwriter writer, object value, newtonsoft.json.jsonserializer serializer) {   jsonserializer inner = this.innerserializer;   jo = jobject.fromobject(value, inner);   //my stuff here   jo.writeto(writer, this); } 

that gives different id each time, if hits same object twice. want use json's usual id resolution custom serialization. how can that?

your idea of using inner serializer not work as-is. id-to-object mapping table held in private field jsonserializerinternalbase._mappings no way copy outer serializer inner serializer.

as alternative, make recursive call serialize using same serializer, , have converter disable using thread-static pushdown stack along lines of generic method of modifying json before being returned client , json.net throws stackoverflowexception when using [jsonconvert()]. need enhance converters in these examples manually check , add necessary "$id" , "$ref" properties making use of jsonserializer.referenceresolver property.

however, since converters add properties, more straightforward solution problem might create custom contract resolver allows types customize contract generated via callback method declared in attribute applied type, instance:

public class modifiercontractresolver : defaultcontractresolver {     // of 7.0.1, json.net suggests using static instance "stateless" contract resolvers, performance reasons.     // http://www.newtonsoft.com/json/help/html/contractresolver.htm     // http://www.newtonsoft.com/json/help/html/m_newtonsoft_json_serialization_defaultcontractresolver__ctor_1.htm     // "use parameterless constructor , cache instances of contract resolver within application optimal performance."     // see https://stackoverflow.com/questions/33557737/does-json-net-cache-types-serialization-information     static modifiercontractresolver instance;      // explicit static constructor tell c# compiler not mark type beforefieldinit     static modifiercontractresolver() { instance = new modifiercontractresolver(); }      public static modifiercontractresolver instance { { return instance; } }      protected override jsonobjectcontract createobjectcontract(type objecttype)     {         var contract = base.createobjectcontract(objecttype);          // apply in reverse order inherited types applied after base types.         foreach (var attr in objecttype.getcustomattributes<jsonobjectcontractmodifierattribute>(true).reverse())         {             var modifier = (jsonobjectcontractmodifier)activator.createinstance(attr.contractmodifiertype, true);             modifier.modifycontract(objecttype, contract);         }         return contract;     } }  public abstract class jsonobjectcontractmodifier {     public abstract void modifycontract(type objecttype, jsonobjectcontract contract); }  [system.attributeusage(attributetargets.class, allowmultiple = true, inherited = true)] public class jsonobjectcontractmodifierattribute : system.attribute {     private readonly type _contractmodifiertype;      public type contractmodifiertype { { return _contractmodifiertype; } }      public jsonobjectcontractmodifierattribute(type contractmodifiertype)     {         if (contractmodifiertype == null)         {             throw new argumentnullexception("contractmodifiertype");         }         if (!typeof(jsonobjectcontractmodifier).isassignablefrom(contractmodifiertype))         {             throw new argumentnullexception(string.format("{0} not subtype of {1}", contractmodifiertype, typeof(jsonobjectcontractmodifier)));         }         this._contractmodifiertype = contractmodifiertype;     }     } 

then, apply types in following example:

[jsonobjectcontractmodifier(typeof(testcontractmodifier))] public class test {     public string { get; set; }     public string b { get; set; }     public string c { get; set; } }  class testcontractmodifier : jsonobjectcontractmodifier {     class emptyvalueprovider : ivalueprovider     {         // explicit static constructor tell c# compiler not mark type beforefieldinit         static emptyvalueprovider() { }          internal static readonly emptyvalueprovider instance = new emptyvalueprovider();          #region ivalueprovider members          public object getvalue(object target)         {             var test = target test;             if (test == null)                 return null;             return test.a == null && test.b == null && test.c == null;         }          public void setvalue(object target, object value)         {             var property = target test;             if (property == null)                 return;             if (value != null && value.gettype() == typeof(bool) && (bool)value == true)             {                 property.a = property.b = property.c = null;             }         }          #endregion     }      public override void modifycontract(type objecttype, jsonobjectcontract contract)     {         var jsonproperty = new jsonproperty         {             propertyname = "isempty",             underlyingname = "isempty",             propertytype = typeof(bool?),             nullvaluehandling = nullvaluehandling.ignore,             readable = true,             writable = true,             declaringtype = typeof(test),             valueprovider = emptyvalueprovider.instance,         };          contract.properties.add(jsonproperty);     } } 

and serialize follows:

var settings = new jsonserializersettings  {      preservereferenceshandling = preservereferenceshandling.objects,  // or preservereferenceshandling.all     contractresolver = modifiercontractresolver.instance,  };  var json = jsonconvert.serializeobject(root, formatting.indented, settings); 

this produces following json:

[   {     "$id": "1",     "a": "hello",     "b": "goodbye",     "c": "sea",     "isempty": false   },   {     "$ref": "1"   },   {     "$id": "2",     "a": null,     "b": null,     "c": null,     "isempty": true   }, } 

as can see, both synthetic "isempty" property , reference handling properties present. prototype fiddle.


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -