我需要序列化一些类(我试图使用JSON.NET)。有些人有自我参考。对于其中的一个,我需要能够决定序列化哪些字段(2个可能的选择)。这堂课很难。这是类的简化示例(Node是特殊类):
// classes
class TreeObject
{ }
class Node : TreeObject // needs to be specially serialized
{
public string name;
public List<TreeObject> childs; // can contain self-reference
public Node()
{
name = null;
childs = new List<TreeObject>();
}
}
我尝试通过继承JsonConverter并覆盖方法来为Node类创建一个JsonConverter:&#34; CanConvert&#34;,&#34; WriteJson&#34; (用于序列化),&#34; ReadJson&#34; (用于反序列化)。
这是我如何尝试使用我的&#34; NodeConverter&#34;:
// create object
Node parent = new Node();
parent.name = null;
parent.childs.Add(parent);
// create settings
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
settings.TypeNameHandling = TypeNameHandling.Auto;
settings.Converters = new[] {new NodeConverter()}; // add my converter
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
// serialize
string json = JsonConvert.SerializeObject(parent, Formatting.Indented, settings);
// expected result
json == @"{
""$id"": ""1"",
""$type"": ""Node, test"",
""childs"": [
{
""$ref"": ""1""
}
]
}"; // the project is called "test"
但是当我尝试将JsonConverter添加到JsonSerializerSettings(用于序列化和反序列化)时,JSON.NET会自动停止处理这些功能。
我花了好几个小时查找如何使这项工作,任何帮助将不胜感激
编辑:我试图缩短我的问题编辑:
string SerializeNode(Node node)
{
if(node.name == null)
{
compress(node);
string strNode = (serialize all fields except the name field);
decompress(node);
return strNode;
}
else
{
return (serialize only the name field);
}
}
Node DeserializeNode(string strNode)
{
if(strNode does not have name field)
{
Node node = new Node();
deserialize all strNode fields and assign them to node;
decompress(node);
return node;
}
else
{
return KnownNodes[strNode name field];
// where KnownNodes is a Dictionary<string, Node>
}
}
当然,我仍然希望JSON.NET保留引用(现在使用PreserveReferencesHandling.Objects选项),并且还包含TypeNameHandling.Auto的类型名称。字典避免了不必要的数据,并确保为所有具有相同名称的对象共享相同的实例。
答案 0 :(得分:0)
[TestMethod]
public void List_Test()
{
var resource = new Resource() { ResourceProperty = "Resource" };
var video = new Video() { ResourceProperty = "Video", VideoProperty = "VideoMP4" };
var list = new List<Resource>() { resource, video };
// Again the important part are the settings
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects
};
var serializedList = JsonConvert.SerializeObject(list, settings);
var deserializedList = JsonConvert.DeserializeObject<List<Resource>> (serializedList, settings);
// And we recover the information with NO data loss
Assert.AreEqual("Resource", deserializedList[0].ResourceProperty);
Assert.AreEqual("VideoMP4", ((Video)deserializedList[1]).VideoProperty);
}
我个人使用字符串扩展名:
public static bool DeserializeJson<T>(this String str, out T item)
{
var returnResult = default(T);
var success = Ui.Instance.Try(
() =>
{
returnResult = new JavaScriptSerializer().Deserialize<T>(str);
},
"Deserializing json " + typeof(T),
"Deserializing json done",
"Deserializing json failed",
isCritical:false
);
item = returnResult;
return success;
}
然后我可以使用
Node node;
if(GetJson(service, out jsonstring) && jsonstring.DeserializeJson(out node)){
或
TreeObject node;
或
... jsonstring.DeserializeJson<TreeObject>(out node)){
答案 1 :(得分:0)
5年后,我遇到了同样的问题。这是保持引用正确解析的示例。请注意对serializer.ReferenceResolver
的调用,它具有神奇的作用。
public class EntityConverter : JsonConverter<Entity>
{
public override void WriteJson( JsonWriter writer, Entity value, JsonSerializer serializer )
{
var me = new JObject();
me["$id"] = new JValue( serializer.ReferenceResolver.GetReference( serializer, value ) );
me["your_array"] = JArray.FromObject( value.components, serializer );
me["your_other_values"] = new JValue( value.tag );
me.WriteTo( writer );
}
public override Entity ReadJson( JsonReader reader, Type objectType, Entity existingValue, bool hasExistingValue, JsonSerializer serializer )
{
var o = JObject.Load( reader );
var id = (string)o["$id"];
if( id != null )
{
var entity = new Entity();
serializer.Populate( o.CreateReader(), entity );
return entity;
}
else
{
var reference = (string)o["$ref"];
return serializer.ReferenceResolver.ResolveReference( serializer, reference ) as Entity;
}
}
}