JSON序列化 - 如何使用JSON.net/Newtonsoft展平嵌套对象结构

时间:2015-06-25 09:32:54

标签: c# json serialization json.net

我有以下JSON结构:

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

我希望在数组中展平MetaData和嵌套的Info和Data对象。我还想使用Name字段作为Text值的字段名称,因此它变为" DataId" :" 8"。

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

到目前为止,我已经使用合同解析器让我到目前为止:

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;
            }
}

如何获得所需的序列化?

1 个答案:

答案 0 :(得分:0)

如果您根本不想修改类型,可以使用LINQ to JSON加载和预处理JSON,如下所示:

        // 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>();

为方便起见,使用几种简单的扩展方法:

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);
    }
}