【问题标题】:Deserialize Json objects with Json.Net使用 Json.Net 反序列化 Json 对象
【发布时间】:2014-08-27 20:18:18
【问题描述】:

我正在尝试使用 Json.net 反序列化一个对象。我能够成功地做到这一点,但它更像是一种 hack,所以我正在寻找一种更好/正确的方法来做到这一点。

{
"page":"admin",
"context":"id",
"records":{
            "rCount":6,
            "1":[
               {
                  "name":"Romeo",
                  "dob":"01\/01\/1970"
               },
               {
                  "name":"Harry",
                  "dob":"10\/10\/2012"
               },
               {
                  "name":"Lee",
                  "dob":"17\/10\/2012"
               }],
            "2":[
               {
                  "name":"Mark",
                  "dob":"01\/01\/1970"
               },
               {
                  "name":"Jack",
                  "dob":"10\/10\/2012"
               },
               {
                  "name":"Json",
                  "dob":"17\/10\/2012"
               }],

}}

这是 records 对象的问题所在的 json 字符串。如果它没有那个 rCount 变量,那么它可以被反序列化为字典,但是由于 rCount 变量它不能被正确地反序列化为字典。反序列化此对象的正确方法应该是什么。

这是我的解决方案:

class Program
{
static void Main(string[] args)
{
    var recordFile = JsonConvert.DeserializeObject<RecordFile>(Properties.Resources.data);
}

public class RecordFile
{
    public string Page { get; set; }
    public string Context { get; set; }
    public Records Records { get; set; }
}

public class Records
{
    public int RCount { get; set; }
    [JsonExtensionData]
    private Dictionary<string, object> _reocordList;

    public List<Record[]> RecordList
    {
        get
        {
            if (_reocordList != null && _reocordList.Count > 0)
            {
                return _reocordList.Values.Select(record => JsonConvert.DeserializeObject<Record[]>(record.ToString())).ToList();
            }
            return new List<Record[]>();
        }
    }

}

public class Record
{
    public string Name { get; set; }
    public string Dob { get; set; }
}
}

【问题讨论】:

  • @AndrewWhitaker 没有其他方法可以对其进行反序列化。由于 JsonExtensionDataAttribute,我正在使用 DictionaryListDictionary 将完成这项工作
  • 是的,我一发表评论就意识到了,哈哈。

标签: c# json serialization json.net


【解决方案1】:

您可以使用 jObject 手动解析 JSON:

public class RecordFile
{
    public string Page { get; set; }
    public string Context { get; set; }
    public Records Records { get; set; }
}

public class Records
{
    public int RCount { get; set; }
    public IDictionary<string, List<Record>> RecordsDictionary { get; set; } 
}


public class Record
{
    public string Name { get; set; }
    public string Dob { get; set; }
}

然后:

var jObject = JObject.Parse(\* your json *\);
var recordFile = new RecordFile
{
    Page = jObject.Value<string>("page"),
    Context = jObject.Value<string>("context"),
    Records = new Records
    {
        RCount = jObject["records"].Value<int>("rCount"),
        RecordsDictionary =
            jObject["records"].Children<JProperty>()
                              .Where(prop => prop.Name != "rCount")
                              .ToDictionary(prop => prop.Name),
                                            prop =>
                                            prop.Value.ToObject<List<Record>>())
    }

};

当然,当属性不存在时,它可以很容易地处理。

【讨论】:

    【解决方案2】:

    我假设你想完全摆脱 Records 类,结果是这样的:

    public class RecordFile
    {
        public string Page { get; set; }
        public string Context { get; set; }
        public Dictionary<string, Record[]> Records { get; set; }
    }
    
    public class Record
    {
        public string Name { get; set; }
        public string Dob { get; set; }
    }
    

    由于您根本不关心 JSON 中的 records.rCount 属性,您可以指定一个新的错误处理程序来简单地忽略该属性:

    var recordFile = JsonConvert.DeserializeObject<RecordFile>(
        jsonString, 
        new JsonSerializerSettings 
        {
            Error = (sender, args) =>
            {
                if (args.ErrorContext.Path == "records.rCount")
                {
                    // Ignore the error
                    args.ErrorContext.Handled = true;
                }
            }
        });
    

    现在,当相关属性遇到错误时,反序列化器将跳过它。另一种选择是编写一个自定义转换器,但忽略一个属性感觉有点过头了。

    示例: https://dotnetfiddle.net/3svPqk

    【讨论】:

      【解决方案3】:

      到目前为止发布的其他答案都应该有效。为了完整起见,我将展示如何使用自定义 JsonConverter 来解决此问题并稍微简化您的模型。

      这是转换器的代码:

      class RecordFileConverter : JsonConverter
      {
          public override bool CanConvert(Type objectType)
          {
              return (objectType == typeof(RecordFile));
          }
      
          public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
          {
              JObject jo = JObject.Load(reader);
              RecordFile rf = new RecordFile();
              rf.Page = (string)jo["page"];
              rf.Context = (string)jo["context"];
              JObject records = (JObject)jo["records"];
              rf.RecordCount = (int)records["rCount"];
              rf.Records = records.Properties()
                                  .Where(p => p.Name != "rCount")
                                  .Select(p => p.Value.ToObject<Record[]>())
                                  .ToList();
              return rf;
          }
      
          public override bool CanWrite
          {
              get { return false; }
          }
      
          public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
          {
              throw new NotImplementedException();
          }
      }
      

      要使用转换器,请更改您的模型类,如下所示。 (注意RecordFile 类有一个JsonConverter 属性来将自定义RecordFileConverter 链接到它。还要注意Records 类已被删除,而RCountRecordList 属性已被移动到RecordFile 类并重命名。)

      [JsonConverter(typeof(RecordFileConverter))]
      public class RecordFile
      {
          public string Page { get; set; }
          public string Context { get; set; }
          public int RecordCount { get; set; }
          public List<Record[]> Records { get; set; }
      }
      
      public class Record
      {
          public string Name { get; set; }
          public string Dob { get; set; }
      }
      

      然后,正常反序列化:

      var recordFile = JsonConvert.DeserializeObject<RecordFile>(json);
      

      演示https://dotnetfiddle.net/jz3zUT

      【讨论】:

      • 非常感谢..这很有帮助
      • 没问题;很高兴我能帮上忙。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 2013-07-25
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      相关资源
      最近更新 更多