![](/img/trans.png)
[英]How can I make reference handling syntax from Jackson and JSON.net compatible?
[英]Handling reference loops in JSON.net
我希望將List<Item>
的集合( List<Item>
)序列化為JSON。
這些項目的集合Connection
,其給出了關於從一個連接信息Item
的第二Item
。 並且由於連接對象具有對項的引用,因此它使其成為無限循環。
我的問題是,在第二次序列化對象時,有一種方法可以跳過連接集的序列化。
我已經嘗試過繼承JsonConverter
和編寫自定義WriteJson()
方法之類的東西,但是從那里開始我是否應該寫出數組。
我也嘗試過使用自定義的ContractResolver,但效果不佳。
類
public class Item
{
private static int _lastID = 0;
public Item()
{
ID = ++_lastID;
Connections = new List<Connection>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public List<Connection> Connections { get; set; }
}
public class Connection
{
private Connection(ConnectionType type, Item source, Item target)
{
if (type == ConnectionType.None)
throw new ArgumentException();
if (source == null)
throw new ArgumentNullException("source");
if (target == null)
throw new ArgumentNullException("target");
Type = type;
Source = source;
Target = target;
}
public ConnectionType Type { get; set; }
public Item Source { get; set; }
public Item Target { get; set; }
public static void Connect(ConnectionType type, Item source, Item target)
{
var conn = new Connection(type, source, target);
source.Connections.Add(conn);
target.Connections.Add(conn);
}
}
通緝結果:
[
{
"id": 1,
"name": "Item #1",
"prop1": "val1",
"prop2": "val2",
"connections": {
"type": "ConnType",
"source": {
"id": 1,
"name": "Item #1",
"prop1": "val1",
"prop2": "val2"
// no connections array
},
"target": {
"id": 2,
"name": "Item #2",
"prop1": "val1",
"prop2": "val2"
// no connections array
}
}
},
{
"id": 2,
"name": "Item #2",
"prop1": "val1",
"prop2": "val2",
"connections": {
"type": "ConnType",
"source": {
"id": 1,
"name": "Item #1",
"prop1": "val1",
"prop2": "val2"
// no connections array
},
"target": {
"id": 2,
"name": "Item #2",
"prop1": "val1",
"prop2": "val2"
// no connections array
}
}
}
]
編輯:
C#
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Formatting = Formatting.Indented
};
settings.Converters.Add(new StringEnumConverter());
var json = JsonConvert.SerializeObject(collection, settings);
將此添加到您的Global.asax(或WebApiConfig或任何其他配置類)
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
您可以引入一個新類,比如ItemClass
,它將包含類Item
所有字段,而不是Connections
屬性,而不是聲明Item
的Source
和Target
類型。
public class ItemClass
{
public int ID { get; set; }
public string Name { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
public class Connection
{
// ...
public ConnectionType Type { get; set; }
public ItemClass Source { get; set; }
public ItemClass Target { get; set; }
// ...
}
現在,您將有相應的填充新ItemClass
類型實例的開銷。
存在一個問題,因為在Json中無法引用對象(請參閱通過標識引用對象的標准方式(例如,循環引用)? )。
這意味着您必須在每次引用時復制一個項目,以便將所有連接帶到客戶端。
我建議只使用id將連接帶到客戶端,將連接作為單獨的對象。
添加JsonIgnore
屬性的Connections
對房地產Item
。
[JsonIgnore]
public List<Connection> Connections { get; set; }
並使用類直接發送到客戶端而不是項目列表。
class ConnectionContainer
{
private readonly List<Item> _items;
private readonly List<ConnectionInfo> _connections;
public ConnectionContainer(IEnumerable<Item> items)
{
_items = items.ToList();
Connections = items.SelectMany(i => i.Connections).Distinct().Select(c => new ConnectionInfo
{
Type = c.Type,
SourceId = c.Source.ID,
TargetId = c.Target.ID
}).ToList();
}
public List<Item> Items
{
get { return _items; }
}
public List<ConnectionInfo> Connections
{
get { return _connections; }
}
}
class ConnectionInfo
{
private ConnectionType Type { get; set; }
private int SourceId { get; set; }
private int TargetId { get; set; }
}
如果我沒有弄錯,你只需要保留包含連接集合的第一個參考深度? 如果是這種情況,請嘗試使用:
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.MaxDepth = 1;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.