如何使Jackson和JSON.net的引用处理语法兼容? [英] How can I make reference handling syntax from Jackson and JSON.net compatible?
问题描述
我有一个服务器,该服务器使用Jackson生成以下JSON.
I have a server that produces the following JSON with Jackson.
{
"$id" : 1,
"employees" : [
{
"$id" : 2,
"name" : "John Rambo",
},
2 // Jackson: reference by ID only
]
}
员工列表包含两次相同的员工.杰克逊第二次通过其ID正确引用了该对象.
The list of employees contains the same employee twice. Jackson correctly references the object by it's ID the second time.
我想在使用JSON.net的客户端中反序列化此操作,但这将不起作用,因为JSON.net希望我将引用包装在具有$ ref属性的json对象中,如下所示:
I want to deserialize this in a client that uses JSON.net, but this won't work because JSON.net expects me to have the reference wrapped in a json object with a $ref property like this:
{
"$id": "1",
"employees" : [
{
"$id": "2",
"name": "John Rambo"
},
{
"$ref": "2" // JSON.net: reference wrapped in JSON object
}
]
}
是否可以通过配置或实现自定义反序列化器使JSON.net正确使用Jackson语法?
Is there a way to make JSON.net correctly consume the Jackson syntax either by configuration or by implementing a custom deserializer?
推荐答案
这是一个应该起作用的自定义转换器:
Here's a custom converter that should work:
public class EmployeeConverter : JsonConverter
{
public override void WriteJson(
JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
List<Employee> employees = null;
if (reader.TokenType == JsonToken.StartArray)
{
JArray arr = serializer.Deserialize<JArray>(reader);
employees = new List<Employee>(arr.Count);
var employeeMap = new Dictionary<int, Employee>();
foreach (var item in arr)
{
if (item.Type == JTokenType.Object)
{
var employee = item.ToObject<Employee>();
employees.Add(employee);
int id = item["$id"].ToObject<int>();
employeeMap.Add(id, employee);
}
else if (item.Type == JTokenType.Integer)
{
Employee employee = null;
int id = item.ToObject<int>();
if (employeeMap.TryGetValue(id, out employee))
{
employees.Add(employee);
}
}
}
}
return employees;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanConvert(Type objectType)
{
return false;
}
}
...,这是您的使用方式:
... and here's how you'd use it:
public class Company
{
public Company()
{
this.Employees = new List<Employee>();
}
[JsonConverter(typeof(EmployeeConverter))]
public List<Employee> Employees { get; set; }
}
示例: https://dotnetfiddle.net/XooyQC
基本上使用自定义转换器对整个数组进行反序列化.首先,将数组反序列化为JArray
,然后检查JArray
的每个元素以查看它是引用还是新对象.
Basically use a custom converter to deserialize the entire array. First, deserialize the array to a JArray
, then inspect each element of the JArray
to see if it's a reference or a new object.
这篇关于如何使Jackson和JSON.net的引用处理语法兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!