JSON Serialisation - How to flatten nested object structures using JSON.net/Newtonsoft

我与影子孤独终老i 提交于 2019-12-08 06:38:39

问题


I have the following JSON structure :

{
       "Name":"",
       "Children":[
          {
             "ID":"1",
             "MetaData":[
                {
                   "Info":{
                      "GUID":"cdee360d-7ea9-477d-994f-12f492b9e1ed"
                   },
                   "Data":{
                      "Text":"8"
                   },
                   "Name":"DataId"
                }
             ]
          }
       ]
    }

and I want to flatten the MetaData and nested Info and Data objects in the array. I also want to use the Name field as a field name for Text value so it becomes "DataId" : "8".

  {
       "Name":"",
       "Children":[
          {
             "ID":"1",
             "GUID":"cdee360d-7ea9-477d-994f-12f492b9e1ed",
             "DataId":"8"
          }
       ]
    }

So far I've used a Contract Resolver to get me so 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 do I go about getting my desired serialisation?


回答1:


If you don't want to modify your types at all, you can use LINQ to JSON to load and preprocess your JSON, like so:

        // Load the JSON into an intermediate JObject
        var rootObj = JObject.Parse(json);

        // Restructure the JObject hierarchy
        foreach (var obj in rootObj.SelectTokens("Children[*]").OfType<JObject>())
        {
            var metadata = obj.SelectToken("MetaData[0]"); // Get the first entry in the "MetaData" array.
            if (metadata != null)
            {
                // Remove the entire "Metadata" property.
                metadata.Parent.RemoveFromLowestPossibleParent();
                // Set the name and value
                var name = metadata.SelectToken("Name");
                var id = metadata.SelectToken("Data.Text");
                if (name != null && id != null)
                    obj[(string)name] = (string)id;
                // Move all other atomic values.
                foreach (var value in metadata.SelectTokens("..*").OfType<JValue>().Where(v => v != id && v != name).ToList())
                    value.MoveTo(obj);
            }
        }
        Debug.WriteLine(rootObj);

        // Now deserialize the preprocessed JObject to the final class
        var root = rootObj.ToObject<RootObject>();

Using a couple of simple extension methods for 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 is JArray || t.Parent is 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 an exception if no parent property found.
        toMove.Remove();
        newParent.Add(toMove);
    }
}


来源:https://stackoverflow.com/questions/31046448/json-serialisation-how-to-flatten-nested-object-structures-using-json-net-newt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!