将Sharepoint 2013搜索结果中的JSON反序列化为MyClass

时间:2017-08-31 10:45:10

标签: c# json serialization json.net

我有一个JSON文本,来自Sharepoint 2013中的搜索,并希望将其反序列化为MyClass列表。 我有一个使用KeyValuePair的解决方案

var results = item["Cells"]["results"].ToObject<List<KeyValuePair<string, string>>>();

但是这种方法会删除日期格式等。一切都以字符串形式结束。例如。 JSON文件中正确的挪威语日期最终为文本中的准Norwenglish日期。

编辑:我正在使用Newtonsoft.Json库。

编辑:日期格式只是问题的一部分。反序列化是我的主要问题。

此示例简化了JSON和类。 JSON文件可以有许多这样的记录,因此它最终会出现在一个对象列表中。你有一个很好的解决方案来反序列化这个JSON吗?

JSON

{
  "__metadata": {
    "type": "SP.SimpleDataRow"
  },
  "Cells": {
    "results": [
      {
        "__metadata": {
          "type": "SP.KeyValue"
        },
        "Key": "Id",
        "Value": "358553",
        "ValueType": "Edm.Int64"
      },
      {
        "__metadata": {
          "type": "SP.KeyValue"
        },
        "Key": "Url",
        "Value": "http://somewhere.com",
        "ValueType": "Edm.String"
      },
      {
        "__metadata": {
          "type": "SP.KeyValue"
        },
        "Key": "Title",
        "Value": "My title",
        "ValueType": "Edm.String"
      },
      {
        "__metadata": {
          "type": "SP.KeyValue"
        },
        "Key": "MyDate",
        "Value": "2017-09-10T11:10:19Z",
        "ValueType": "Edm.DateTime"
      }
    ]
  }
}

public class MyClass
{
    public int Id { get; set; }
    public string Url { get; set; }
    public string Title { get; set; }
    public DateTime MyDate { get; set; }
}

1 个答案:

答案 0 :(得分:1)

您可以使用以下转换器反序列化JSON中的"results"数组:

public class KeyValuePropertyArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var pairs = serializer.Deserialize<List<KeyValuePair<string, JToken>>>(reader);
        var jObj = new JObject(pairs.Select(p => new JProperty(p.Key, p.Value)));
        existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        serializer.Populate(jObj.CreateReader(), existingValue);
        return existingValue;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后按如下方式定义MyClass

public class MyClass
{
    public long Id { get; set; } // This should be long not int
    public string Url { get; set; }
    public string Title { get; set; }
    public DateTime MyDate { get; set; }
}

然后,按以下步骤反序列化:

// Disable date recognition while parsing intermediate JToken representation as shown in
// https://stackoverflow.com/questions/35138346/jtoken-get-raw-original-json-value/35141787
var item = JsonConvert.DeserializeObject<JObject>(jsonString, new JsonSerializerSettings { DateParseHandling = DateParseHandling.None });

var finalSettings = new JsonSerializerSettings
{
    Converters = { new KeyValuePropertyArrayConverter<MyClass>() /*, Add some appropriate IsoDateTimeConverter if required, */ },
    // Or set DateFormatString if required
};
var myClass = item["Cells"]["results"].ToObject<MyClass>(JsonSerializer.CreateDefault(finalSettings));

注意:

  1. 您的JSON仅对应于MyClass的单个实例 - 而不是它们的数组。 JSON中唯一的数组是属性值数组。

  2. JSON指定"Id""Edm.Int64",因此我将MyClass.Id修改为long

  3. 通过在加载初始DateParseHandling = DateParseHandling.None时设置JObject,您可以将日期字符串识别推迟到最终反序列化,此时您可以应用适当的IsoDateTimeConverterDateFormatString,和Json.NET可以在最终目标类中使用类型信息,以帮助识别嵌入在JSON中的日期。

  4. 我没有将序列化实现为相同的格式,因为您的问题没有请求此。

  5. 示例.Net fiddle