我正在使用Json.Net进行Json反序列化。有时我读的Json字符串是不正确的(我不能修复,因为我不生成它)。特别是,在一个特定的地方,应该有一个字符串,有时会有一个序列化的对象。然后,Json.Net抱怨并不奇怪地找到一个预期字符串的对象。
我发现我可以在Error
中使用JsonSerializerSettings
拦截此问题,并通过设置ErrorContext.Handled
使Json.Net忽略此问题。但我想做更多。如果我可以查看序列化对象,我可以弄清楚字符串应该是什么,并在理论上提供正确的答案。在实践中,我无法想象我们如何做到这一点。特别是在错误处理程序中:
ErrorContext.Handled
,解析器可以成功继续,因此它可以正确地确定问题字符串的开始和结束)?[编辑] 根据要求提供了一个简化的例子:
我要解析的错误的Json字符串:
{
"id": 2623,
"name": {
"a": 39,
"b": 0.49053320637463277,
"c": "cai5z+A=",
"name": "22"
},
"children": [
{
"id": 3742,
"name": {
"a": 37,
"b": 0.19319664789046936,
"c": "Me/KKPY=",
"name": "50"
},
"children": [
{
"id": 1551,
"name": {
"a": 47,
"b": 0.6935373953047849,
"c": "qkGkMwY=",
"name": "9"
},
"children": []
},
{
"id": 4087,
"name": {
"a": 5,
"b": 0.42905938319352427,
"c": "VQ+yH6o=",
"name": "84"
},
"children": []
},
{
"id": 614,
"name": {
"a": 19,
"b": 0.7610801005554758,
"c": "czjTK1s=",
"name": "11"
},
"children": []
}
]
},
{
"id": 3382,
"name": {
"a": 9,
"b": 0.36416331043660793,
"c": "lnoHrd0=",
"name": "59"
},
"children": [
{
"id": 4354,
"name": {
"a": 17,
"b": 0.8741648112769075,
"c": "CD2i2I0=",
"name": "24"
},
"children": []
},
{
"id": 2533,
"name": {
"a": 52,
"b": 0.8839575992356788,
"c": "BxFEzVI=",
"name": "60"
},
"children": []
},
{
"id": 5733,
"name": {
"a": 4,
"b": 0.7230552787534219,
"c": "Un7lJGM=",
"name": "30"
},
"children": []
}
]
},
{
"id": 9614,
"name": {
"a": 81,
"b": 0.4015882813379114,
"c": "dKgyRZk=",
"name": "63"
},
"children": [
{
"id": 7831,
"name": {
"a": 81,
"b": 0.2784254314743101,
"c": "xZur64o=",
"name": "94"
},
"children": []
},
{
"id": 6293,
"name": {
"a": 73,
"b": 0.32629523068959604,
"c": "lMkosP4=",
"name": "93"
},
"children": []
},
{
"id": 5253,
"name": {
"a": 13,
"b": 0.19240453242901923,
"c": "oOPZ3tA=",
"name": "5"
},
"children": []
}
]
}
]
}
然后在课堂上解析它:
class Node
{
[JsonProperty]
int id;
[JsonProperty]
string name;
[JsonProperty]
List<Node> children;
}
正如您所看到的,它需要一个字符串name
,但有时会错误地获取一个序列化对象(其中包含有问题的字符串作为成员)。这只发生在一些JSON字符串中,而不发生在其他字符串中,所以我不能只改变Node的类定义来匹配。
[编辑2] 根据我的API,“正确”的Json字符串将如下所示:
{
"id": 2623,
"name": "22",
"children": [
{
"id": 3742,
"name": "50",
"children": [
{
"id": 1551,
"name": "9",
"children": []
},
{
"id": 4087,
"name":"84",
"children": []
},
...
答案 0 :(得分:2)
如您所见,尝试在事后检测错误,然后从错误点重新分析将会出现问题。幸运的是,您所描述的问题可以使用自定义JsonConverter
以简单的方式解决。我们的想法是让转换器将数据读入一个临时结构,该结构可以处理表单(对象或字符串),查询类型,然后从那里构造Node
。
以下是转换器的代码:
class NodeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Node));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
Node node = new Node();
node.id = (int)jo["id"];
JToken name = jo["name"];
if (name.Type == JTokenType.String)
{
// The name is a string at the current level
node.name = (string)name;
}
else
{
// The name is one level down inside an object
node.name = (string)name["name"];
}
node.children = jo["children"].ToObject<List<Node>>(serializer);
return node;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,请在[JsonConverter]
类中添加Node
属性,如下所示:
[JsonConverter(typeof(NodeConverter))]
class Node
{
public int id { get; set; }
public string name { get; set; }
public List<Node> children { get; set; }
}
然后你可以正常反序列化:
Node node = JsonConvert.DeserializeObject<Node>(json);
这是一个完整的演示,展示了转换器的运行情况。为了便于说明,我创建了一个新的JSON字符串,其中包含您在问题中描述的“好”和“坏”节点的组合。
class Program
{
static void Main(string[] args)
{
string json = @"
{
""id"": 2623,
""name"": {
""a"": 39,
""b"": 0.49053320637463277,
""c"": ""cai5z+A="",
""name"": ""22""
},
""children"": [
{
""id"": 3741,
""name"": ""50"",
""children"": [
{
""id"": 1550,
""name"": ""9"",
""children"": []
},
{
""id"": 4088,
""name"": {
""a"": 5,
""b"": 0.42905938319352427,
""c"": ""VQ+yH6o="",
""name"": ""85""
},
""children"": []
}
]
},
{
""id"": 3742,
""name"": {
""a"": 37,
""b"": 0.19319664789046936,
""c"": ""Me/KKPY="",
""name"": ""51""
},
""children"": [
{
""id"": 1551,
""name"": {
""a"": 47,
""b"": 0.6935373953047849,
""c"": ""qkGkMwY="",
""name"": ""10""
},
""children"": []
},
{
""id"": 4087,
""name"": ""84"",
""children"": []
}
]
}
]
}";
Node node = JsonConvert.DeserializeObject<Node>(json);
DumpNode(node, "");
}
private static void DumpNode(Node node, string indent)
{
Console.WriteLine(indent + "id = " + node.id + ", name = " + node.name);
foreach(Node child in node.children)
{
DumpNode(child, indent + " ");
}
}
}
输出:
id = 2623, name = 22
id = 3741, name = 50
id = 1550, name = 9
id = 4088, name = 85
id = 3742, name = 51
id = 1551, name = 10
id = 4087, name = 84