c# - Implementing ASP.NET Web API Optional Parameters -


i need ability distinguish between key not being supplied , null.

an example of json be:

# key not specified {}   # key specified null {'optionalkey' : null}  # key specified , valid {'optionalkey' : 123} 

to distinguishable between key's absence , null, i've created generic optional class wraps each field, requires writing custom jsonconverter , defaultcontractresolver flatten json / unpack optionaltype (sending nested json each field not option).

i've managed create linqpad script can't thinking there must easier way doesn't involve reflection?

void main() {     //null     settings settings = null;     jsonconvert.serializeobject(settings, new jsonserializersettings() { contractresolver = new shouldserializecontractresolver() }).dump();      settings = new settings();      // no key {}     settings.optionalintegersetting = null;     jsonconvert.serializeobject(settings, new jsonserializersettings() { contractresolver = new shouldserializecontractresolver() }).dump();      // null key {\"optionalintegersetting\" : null}     settings.optionalintegersetting = new optional<uint?>(); // assigning null assigns optional type class, not use implict operators.     jsonconvert.serializeobject(settings, new jsonserializersettings() { contractresolver = new shouldserializecontractresolver() }).dump();      // has value {\"optionalintegersetting\" : 123}     settings.optionalintegersetting = 123;     jsonconvert.serializeobject(settings, new jsonserializersettings() { contractresolver = new shouldserializecontractresolver() }).dump();      jsonconvert.deserializeobject<settings>("{}").dump();     jsonconvert.deserializeobject<settings>("{'optionalintegersetting' : null}").dump();     jsonconvert.deserializeobject<settings>("{'optionalintegersetting' : '123'}").dump(); // supplying 'a string' instead of '123' breaks optionalconverter.readjson  }  public class settings {     public optional<uint?> optionalintegersetting { get; set; } }  [jsonconverter(typeof(optionalconverter))] public class optional<t> {     public t value { get; set; }      public optional() { }      public optional(t value)     {         value = value;     }      public static implicit operator optional<t>(t t)     {         return new optional<t>(t);     }      public static implicit operator t(optional<t> t)     {         return t.value;     } }  // provides way of populating poco resource model canserialise proerties @ point before serialisation. // prevents having define canserialisemyproperty method each property. public class shouldserializecontractresolver : defaultcontractresolver {     protected override jsonproperty createproperty(memberinfo member, memberserialization memberserialization)     {         jsonproperty property = base.createproperty(member, memberserialization);         if (property.propertytype.isgenerictype && property.propertytype.getgenerictypedefinition() == typeof(optional<>))         {             // add additional shouldserialize property omit no json             property.shouldserialize = instance =>                 instance.gettype().getproperty(property.propertyname).getvalue(instance) != null;         }         return property;     } }  // performs conversion , json value compound type public class optionalconverter : jsonconverter {     public override bool canwrite => true;     public override bool canread => true;      public override bool canconvert(type objecttype)     {         return objecttype.isgenerictype && objecttype.getgenerictypedefinition() == typeof(optional<>);     }      public override object readjson(jsonreader reader, type objecttype, object existingvalue, jsonserializer serializer)     {         var jtoken = jtoken.load(reader);         var generictypeargument = objecttype.getgenericarguments()[0];         var constructor = objecttype.getconstructor(new[] { generictypeargument });         var result = jtokentype.null != jtoken.type ? jtoken.toobject(generictypeargument) : null;          return constructor.invoke(new object[] { jtokentype.null != jtoken.type ? jtoken.toobject(generictypeargument) : null });     }      public override void writejson(jsonwriter writer, object value, jsonserializer serializer)     {         var val = value.gettype().getproperty("value").getvalue(value);         (val != null ? jvalue.fromobject(val) : jvalue.createnull()).writeto(writer);     } } 

full credit goes @dbc.

void main() {     var settings = new settings();      // no key {}     settings.optionalintegersetting = null;     jsonconvert.serializeobject(settings).dump();      // null key {\"optionalintegersetting\" : null}     settings.optionalintegersetting = null;     settings.optionalintegersettingspecified = true;     jsonconvert.serializeobject(settings).dump();      // has value {\"optionalintegersetting\" : 123}     settings.optionalintegersetting = 123;     jsonconvert.serializeobject(settings).dump();      jsonconvert.deserializeobject<settings>("{}").dump();     jsonconvert.deserializeobject<settings>("{'optionalintegersetting' : null}").dump();     jsonconvert.deserializeobject<settings>("{'optionalintegersetting' : '123'}").dump(); }  public class settings {     public uint? optionalintegersetting { get; set; }      [jsonignore]     public bool optionalintegersettingspecified { get; set;} } 

Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -