我正在使用Json.NET进行序列化,但结果字符串的结尾时间过长,因为它包含了大量关于我没有用的程序集的剩余信息。
例如,以下是其中一种类型的内容:
"Assets.Logic.CompGroundType, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null": {
"$type": "Assets.Logic.CompGroundType, Assembly-CSharp",
"GroundType": 1,
"EntityID": 1,
"<GroundType>k__BackingField": 1
}
&#34; GroundType&#34;是一个枚举,&#34; EntityID&#34;是int。
这是我想要的结果:
"Assets.Logic.CompGroundType" : {
"$type": "Assets.Logic.CompGroundType",
"GroundType": 1,
"EntityID": 1,
"<GroundType>k__BackingField": 1
}
如果可能,我还想删除&#34; $ type&#34;仍然正确反序列化继承类型的字段(我不确定为什么它是必要的,因为该信息是从上面的一行重复,但如果我通过设置TypeNameHandling.None删除它,我得到反序列化错误的孩子类型)。我也不确定最后一个字段(k__BackingField)是什么。
如果可能的话,我想进一步减少它:
"Assets.Logic.CompGroundType" : {
"GroundType": 1,
"EntityID": 1,
}
我理解可以手动为Json.Net中的每种类型自定义序列化方案,但我有数百种类型,所以我想通过一些全局设置自动完成。
我尝试更改&#34; FormatterAssemblyStyle&#34;,但没有选项&#34;无&#34;那里,只有&#34;简单&#34;或者&#34; Full&#34;,我已经在使用&#34;简单&#34;。
提前感谢您的帮助。
编辑:
注意类型是字典中的键是很重要的。这就是为什么类型出现两次(在第一个例子的第一和第二行)。
实现自定义SerializationBinder后,我能够减少&#34; $ type&#34;的长度。字段,但不是字典键字段。现在我得到以下内容:
"componentDict": {
"Assets.Logic.CompGroundType, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null": {
"$type": "Assets.Logic.CompGroundType",
"GroundType": 1,
"EntityID": 1,
"<GroundType>k__BackingField": 1
}
}
编辑2:
我尝试序列化的代码是entity component system。我将尝试提供代码示例的详细示例。
所有组件(包括上面的CompGroundType
)都继承自以下抽象类:
abstract class Component
{
public int EntityID { get; private set; }
protected Component(int EntityID)
{
this.EntityID = EntityID;
}
}
我遇到的问题是Entity
班级的序列化问题。 componentDict
:
class Entity
{
readonly public int id;
private Dictionary<Type, Component> componentDict = new Dictionary<Type, Component>();
[JsonConstructor]
private Entity(Dictionary<Type, Component> componentDict, int id)
{
this.id = id;
this.componentDict = componentDict;
}
}
componentDict
包含附加到实体的所有组件。在每个条目<Type, Component>
中,值的类型等于键。
我正在使用以下JsonSerializerSettings
JsonSerializerSettings serializerSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new MyContractResolver(),
TypeNameHandling = TypeNameHandling.Auto,
SerializationBinder = new TypesWithNoAssmeblyInfoBinder(),
Formatting = Formatting.Indented
}
其中MyContractResolver
与this answer形式相同。
TypesWithNoAssmeblyInfoBinder
执行编辑1的更改:
private class TypesWithNoAssmeblyInfoBinder : ISerializationBinder
{
public Type BindToType(string assemblyName, string typeName)
{
return Type.GetType(typeName);
}
public void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.FullName;
}
}
序列化本身如下:
var jsonSerializer = JsonSerializer.Create(serializerSettings);
using (FileStream zippedFile = new FileStream(Application.persistentDataPath + fileName, FileMode.Create))
{
using (GZipStream archive = new GZipStream(zippedFile, CompressionLevel.Fastest))
{
using (StreamWriter sw = new StreamWriter(archive))
{
jsonSerializer.Serialize(sw, savedData);
}
}
}
编辑4:
CompGroundType
类(已完成组件的示例):
class CompGroundType : Component
{
public enum Type {Grass, Rock};
public Type GroundType { get; private set; }
[JsonConstructor]
private CompGroundType(Type groundType, int entityID) : base(entityID)
{
this.GroundType = groundType;
}
}
答案 0 :(得分:1)
第一部分是嵌入式$类型信息,由json.net注入以帮助稍后反序列化。我认为文档中的this example会做你想要的。
public class KnownTypesBinder : ISerializationBinder
{
public IList<Type> KnownTypes { get; set; }
public Type BindToType(string assemblyName, string typeName)
{
return KnownTypes.SingleOrDefault(t => t.Name == typeName);
}
public void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.Name;
}
}
public class Car
{
public string Maker { get; set; }
public string Model { get; set; }
}
KnownTypesBinder knownTypesBinder = new KnownTypesBinder
{
KnownTypes = new List<Type> { typeof(Car) }
};
Car car = new Car
{
Maker = "Ford",
Model = "Explorer"
};
string json = JsonConvert.SerializeObject(car, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
SerializationBinder = knownTypesBinder
});
Console.WriteLine(json);
// {
// "$type": "Car",
// "Maker": "Ford",
// "Model": "Explorer"
// }
object newValue = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
SerializationBinder = knownTypesBinder
});
Console.WriteLine(newValue.GetType().Name);
// Car
只需要根据您的特定需求进行调整。
然后第二部分是字典键,它来自被序列化的Type对象。
我认为您可以通过creating a custom JsonConverter自定义,但事实证明字典键具有“特殊”处理,这意味着更复杂的解决方法。我没有一个更复杂的解决方法的例子抱歉。