如何"展平"一些JSON与JSON.NET?

时间:2015-05-22 06:43:51

标签: c# json

我一直在遇到这种情况,我想将一些JSON反序列化为一个与JSON结构完全匹配的类型。例如,如果我有这样的JSON:

"foo": {
  "bar": {
    "1": 10,
    "4": 20,
    "3": 30,
    "2": 40,
    "5": 50
  },
}

然后我需要这样的东西:

class Bar
{
  [JsonProperty]
  int One;
  [JsonProperty]
  int Two;
  [JsonProperty]
  int Three;
  [JsonProperty]
  int Four;
  [JsonProperty]
  int Five;
}

class Foo
{
  [JsonProperty]
  Bar bar;
}

但如果我想把它变成这个呢?

class Foo
{
  int[] values;
}

通过从每个索引中减去1并将数组从中转出来,将键转换为基于0的索引?我怎么能这样做?

我还有许多其他这种反序列化的例子,但我只是为了说明而发布了另一个例子,因为我不想要一个适合这个确切例子的解决方案,但是而是我可以概括的东西。

"foo": {
  "bar": [
    {
      // Bunch of unimportant stuff
    },
    {
      // Something about the structure of this object alerts me to the fact that this is an interesting record.
      "baz": 12
    },
    {
      // Bunch of unimportant stuff
    }
  ]
}

我想把它变成:

class Foo
{
  int baz;
}

我已经查看了一些CustomCreationConverters的示例,例如this,但我无法使其中提供的解决方案适应上述任何一种情况。

1 个答案:

答案 0 :(得分:2)

  

//关于这个对象结构的一些事情提醒我这是一个有趣的记录。

我认为JSON对象的结构不应该告诉它“重要性”。客户端不应发送任何不相关的信息,或者您必须在应用程序的某处编写自定义代码,以从JSON对象中选择相关信息。业务规则应确定数据的重要性。将JSON视为简单数据。

至于你的第一个例子,你可以使用CustomCreationConverters(正如你所提到的)和LINQ to JSON来处理这样的问题:

public class Foo
{
    public int[] Values { get; set; }
}

public class FooConverter : CustomCreationConverter<Foo> 
{
    public override Foo Create(Type objectType)
    {
        return new Foo();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {

        // Load JObject from stream
        JObject jObject = JObject.Load(reader);

        // Create target object based on JObject
        Foo target = Create(objectType);

        // get the properties inside 'bar' as a list of JToken objects
        IList<JToken> results = jObject["foo"]["bar"].Children().ToList();

        IList<int> values = new List<int>();

        // deserialize the tokens into a list of int values
        foreach (JToken result in results)
        {
            int val = JsonConvert.DeserializeObject<int>(result.First.ToString());
            values.Add(val);
        }

        target.Values = values.ToArray();

        return target;
    }
}

像这样使用:

string fooText = @"{'foo': {
                             'bar': {
                                '1': 10,
                                '4': 20,
                                '3': 30,
                                '2': 40,
                                '5': 50
                              },
                            }
                           }";


Foo foo = JsonConvert.DeserializeObject<Foo>(fooText, new FooConverter());

您可以在JSON.NET文档中了解有关CustomCreationConverters以及如何反序列化部分JSON片段的更多信息:

http://www.newtonsoft.com/json/help/html/CustomCreationConverter.htm

http://www.newtonsoft.com/json/help/html/SerializingJSONFragments.htm