in web api project, right i'm skipping null values. therefore, return json ignores null values , prints property.
in global.asax file:
//manage null in response var json = globalconfiguration.configuration.formatters.jsonformatter; json.serializersettings.nullvaluehandling = newtonsoft.json.nullvaluehandling.ignore;
however, want replace null values "-". but, dont want use data member attribute each property...
[defaultvalue("-")].
i have more 10 classes in project... so, not elegant solution.
i wish simple solution , apply conversion, null values global.asax
example.
public class user { public string user { get; set; } public string name { get; set; } public string dni { get; set; } }
when exists data, service return
{ "user": "usertest", "name": "nametest", "dni": "123456789" }
but, when dni, doesn't exists, respond this
{ "user": "usertest", "name": "nametest", "dni": "" }
so, respond follows
{ "user": "usertest", "name": "nametest", "dni": "-" }
i don't recommend doing this. problem if 1 if string-value properties happens have same value "null value" "-"
, lose information when serializing, namely whether or not property null.
that being said, can contractresolver
overriding jsonproperty.valueprovider
string-valued properties:
public class stringremappingcontractresolver : defaultcontractresolver { static readonly object nullvalue; static stringremappingcontractresolver() { nullvalue = new object(); } readonly dictionary<object, object> map; readonly ilookup<object, object> reversemap; public stringremappingcontractresolver() : this(new keyvaluepair<object, object> [] { new keyvaluepair<object, object>(null, "-")}) { } public stringremappingcontractresolver(ienumerable<keyvaluepair<object, object>> map) { if (map == null) throw new argumentnullexception("map"); this.map = map.todictionary(p => p.key ?? nullvalue, p => p.value); this.reversemap = map.tolookup(p => p.value ?? nullvalue, p => p.key); } class stringremappingvalueprovider : ivalueprovider { readonly ivalueprovider baseprovider; readonly dictionary<object, object> map; readonly ilookup<object, object> reversemap; public stringremappingvalueprovider(ivalueprovider baseprovider, dictionary<object, object> map, ilookup<object, object> reversemap) { if (baseprovider == null) throw new argumentnullexception("baseprovider"); this.baseprovider = baseprovider; this.map = map; this.reversemap = reversemap; } #region ivalueprovider members public object getvalue(object target) { var value = baseprovider.getvalue(target); object mapped; if (map.trygetvalue(value ?? nullvalue, out mapped)) value = mapped; return value; } public void setvalue(object target, object value) { foreach (var mapped in reversemap[value ?? nullvalue]) { // use first. value = mapped; break; } baseprovider.setvalue(target, value); } #endregion } protected override jsonproperty createproperty(memberinfo member, memberserialization memberserialization) { var property = base.createproperty(member, memberserialization); if (property.propertytype == typeof(string)) { property.valueprovider = new stringremappingvalueprovider(property.valueprovider, map, reversemap); } return property; } }
then use like:
public class user { public string user { get; set; } public string name { get; set; } public string dni { get; set; } } public class testclass { public static void test() { var settings = new jsonserializersettings { contractresolver = new stringremappingcontractresolver() }; var user = new user { user = "usertest", name = "nametest", dni = null }; var json = jsonconvert.serializeobject(user, settings); debug.writeline(json); // prints {"user":"usertest","name":"nametest","dni":"-"} debug.assert(jtoken.deepequals(jtoken.parse(json), jtoken.parse(@"{'user':'usertest','name':'nametest','dni':'-'}"))); // no assert var userback = jsonconvert.deserializeobject<user>(json, settings); debug.assert(user.dni == userback.dni && user.name == userback.name && user.user == userback.user); // no assert } }
Comments
Post a Comment