我正在尝试用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; }
}
}
答案 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;
}
}
});
现在,当遇到有问题的属性错误时,反序列化器将跳过它。另一种选择是编写一个自定义转换器,但这样做只是为了忽略一个属性。
答案 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
类已删除,而RCount
和RecordList
属性已移至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);