c# - JSON Serialisation - How to flatten nested object structures using JSON.net/Newtonsoft -
i have following json structure :
{ "name":"", "children":[ { "id":"1", "metadata":[ { "info":{ "guid":"cdee360d-7ea9-477d-994f-12f492b9e1ed" }, "data":{ "text":"8" }, "name":"dataid" } ] } ] }
and want flatten metadata , nested info , data objects in array. want use name field field name text value becomes "dataid" : "8".
{ "name":"", "children":[ { "id":"1", "guid":"cdee360d-7ea9-477d-994f-12f492b9e1ed", "dataid":"8" } ] }
so far i've used contract resolver me far:
private class dynamiccontractresolver : defaultcontractresolver { private readonly list<string> _propertiestoserialize; private readonly list<string> _itemtypenames; public dynamiccontractresolver(list<string> propertiestoserialize, list<string> itemtypenames) { _propertiestoserialize = propertiestoserialize; _itemtypenames = itemtypenames; } protected override ilist<jsonproperty> createproperties(type type, memberserialization memberserialization) { var properties = base.createproperties(type, memberserialization); properties = properties.where(p => _propertiestoserialize.contains(p.propertyname)).tolist(); } return properties; } }
how go getting desired serialisation?
if don't want modify types @ all, can use linq json load , preprocess json, so:
// load json intermediate jobject var rootobj = jobject.parse(json); // restructure jobject hierarchy foreach (var obj in rootobj.selecttokens("children[*]").oftype<jobject>()) { var metadata = obj.selecttoken("metadata[0]"); // first entry in "metadata" array. if (metadata != null) { // remove entire "metadata" property. metadata.parent.removefromlowestpossibleparent(); // set name , value var name = metadata.selecttoken("name"); var id = metadata.selecttoken("data.text"); if (name != null && id != null) obj[(string)name] = (string)id; // move other atomic values. foreach (var value in metadata.selecttokens("..*").oftype<jvalue>().where(v => v != id && v != name).tolist()) value.moveto(obj); } } debug.writeline(rootobj); // deserialize preprocessed jobject final class var root = rootobj.toobject<rootobject>();
using couple of simple extension methods convenience:
public static class jsonextensions { public static void removefromlowestpossibleparent(this jtoken node) { if (node == null) throw new argumentnullexception(); var contained = node.ancestorsandself().where(t => t.parent jarray || t.parent jobject).firstordefault(); if (contained != null) contained.remove(); } public static void moveto(this jtoken token, jobject newparent) { if (newparent == null) throw new argumentnullexception(); var tomove = token.ancestorsandself().oftype<jproperty>().first(); // throws exception if no parent property found. tomove.remove(); newparent.add(tomove); } }
Comments
Post a Comment