I am serializing using Json.NET, but the resulting string ends up way too long, because it includes a ton of surplus info about the assembly that I have no use for.
For example, here is what I'm getting for one of the types:
"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
}
"GroundType" is an enum, and "EntityID" is int.
Here is my desired result:
"Assets.Logic.CompGroundType" : {
"$type": "Assets.Logic.CompGroundType",
"GroundType": 1,
"EntityID": 1,
"<GroundType>k__BackingField": 1
}
If it's possible, I would also like to remove the "$type" field while still correctly deserializing inherited types (I'm not sure why it's necessary, since that info is duplicated from one line above, but if I remove it by setting TypeNameHandling.None, I get deserialization errors for child types). I am also not sure what the last field (k__BackingField) is for.
If it's possible, I would want to reduce it even further, to:
"Assets.Logic.CompGroundType" : {
"GroundType": 1,
"EntityID": 1,
}
I understand it's possible to manually customize the serialization scheme for each type in Json.Net, but I have hundreds of types, and so I would like to do it automatically through some global setting.
I tried changing "FormatterAssemblyStyle", but there is no option for "None" there, only "Simple" or "Full", and I'm already using "Simple".
Thanks in advance for any help.
Edit:
It's important to note that the types are keys in a dictionary. That's why the type appears twice (in the first and second row of the first example).
After implementing a custom SerializationBinder, I was able to reduce the length of the "$type" field, but not the Dictionary key field. Now I get the following:
"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
      }
    }
Edit 2:
The code I'm trying to serialize is an entity component system. I'll try to provide a detailed example with code samples.
All components (including CompGroundType above) inherit from the following abstract class:
abstract class Component
{
    public int EntityID { get; private set; }
    protected Component(int EntityID)
    {
        this.EntityID = EntityID;
    }
}
The issue I'm encountering is in the serialization of the Entity class' 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 contains all the components attached to the entity. In each entry <Type, Component>, the type of the value is equal to the key.
I am doing the serialization recursively, using the following JsonSerializerSettings:
JsonSerializerSettings serializerSettings = new JsonSerializerSettings()
{
     ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
     ContractResolver = new MyContractResolver(),
     TypeNameHandling = TypeNameHandling.Auto,
     SerializationBinder = new TypesWithNoAssmeblyInfoBinder(),
     Formatting = Formatting.Indented
}
Where MyContractResolver is identical to the one form this answer.
TypesWithNoAssmeblyInfoBinder does the change from edit 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;
            }
        }
The serialization itself is done as follows:
            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);
                    }
                }
            }
Edit 4:
The CompGroundType class (an example of a finished component):
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;
    }
}