使用Json.Net反序列化Json对象

时间:2014-08-27 20:18:18

标签: c# json serialization json.net

我正在尝试用Json.net反序列化一个对象。我能够成功地完成它,但它更像是一个黑客,所以我正在寻找一种更好/更合适的方法。

{
"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"
               }],

}}

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

3 个答案:

答案 0 :(得分:1)

我假设你想完全摆脱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

答案 1 :(得分: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 :(得分:1)

到目前为止发布的其他答案都应该有效。为了完整起见,我将展示如何使用自定义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