我正在使用json.net进行json避难所化。有时我读的JSON字符串不正确(由于我不产生它,因此无法修复)。特别是在一个特定的地方,应该有一个字符串,有时会有一个序列化对象。然后,JSON.NET抱怨要找到一个对象期望字符串的对象。
我发现我可以通过在JsonSerializerSettings
中使用Error
拦截这一点,还可以通过设置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字符串中,而不会发生在其他字符串中,因此我不能仅更改匹配节点的类定义。
[编辑2]根据我的API,"正确"的JSON字符串看起来像这样:
{
"id": 2623,
"name": "22",
"children": [
{
"id": 3742,
"name": "50",
"children": [
{
"id": 1551,
"name": "9",
"children": []
},
{
"id": 4087,
"name":"84",
"children": []
},
...
试图在事实后检测错误,然后从错误点上恢复出现,如您所见。幸运的是,您所描述的问题可以使用自定义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();
}
}
要使用转换器,请在您的Node
类中添加[JsonConverter]
属性:
[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字符串,其中包含您在问题中描述的"好"one_answers"坏"节点的组合。
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