加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Json.NET:如何从生成的json字符串中的类型中删除汇编信息

发布时间:2020-12-15 22:48:51 所属栏目:百科 来源:网络整理
导读:我正在使用Json.NET进行序列化,但结果字符串的结尾时间太长,因为它包含了大量关于我没有用的程序集的剩余信息. 例如,以下是我为其中一种类型获取的内容: "Assets.Logic.CompGroundType,Assembly-CSharp,Version=0.0.0.0,Culture=neutral,PublicKeyToken=nul
我正在使用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
}

“GroundType”是枚举,“EntityID”是int.

这是我想要的结果:

"Assets.Logic.CompGroundType" : {
"$type": "Assets.Logic.CompGroundType","<GroundType>k__BackingField": 1
}

如果可能的话,我还想删除“$type”字段,同时仍然正确地反序列化继承的类型(我不确定为什么它是必要的,因为该信息是从上面的一行重复,但如果我通过设置TypeNameHandling删除它.没有,我得到了子类型的反序列化错误.我也不确定最后一个字段(k__BackingField)的用途.

如果有可能,我想进一步减少它,以:

"Assets.Logic.CompGroundType" : {
"GroundType": 1,}

我知道可以在Json.Net中为每种类型手动定制序列化方案,但我有数百种类型,所以我想通过一些全局设置自动完成.

我尝试更改“FormatterAssemblyStyle”,但没有“None”选项,只有“Simple”或“Full”,我已经使用“Simple”了.

在此先感谢您的帮助.

编辑:

重要的是要注意类型是字典中的键.这就是类型出现两次的原因(在第一个例子的第一行和第二行).

实现自定义SerializationBinder后,我能够减少“$type”字段的长度,但不能缩短Dictionary键字段的长度.现在我得到以下内容:

"componentDict": {
      "Assets.Logic.CompGroundType,PublicKeyToken=null": {
        "$type": "Assets.Logic.CompGroundType","<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;
    }
}

解决方法

第一部分是嵌入式$类型信息,由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 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,SerializationBinder = knownTypesBinder
});

Console.WriteLine(newValue.GetType().Name);
// Car

它只需要根据您的特定需求进行调整.

然后第二部分是字典键,它来自被序列化的Type对象.

我认为你可以在creating a custom JsonConverter之前自定义它,但事实证明字典键有“特殊”处理,这意味着更复杂的解决方法.我没有一个更复杂的解决方法的例子抱歉.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读