序列化对象的自定义 $type 值

5 c# json.net

我们TypeNameHandling = TypeNameHandling.Objects在序列化程序设置中使用 Web API 和 Json.Net 。这工作正常,但我们只在客户端使用类型信息,从不用于反序列化。我们的序列化对象如下所示:

{
    "$type": "PROJECTNAME.Api.Models.Directory.DtoName, PROJECTNAME.Api",
    "id": 67,
    "offices": [{
        "$type": "PROJECTNAME.Api.Models.Directory.AnotherDtoName, PROJECTNAME.Api",
        "officeName": "FOO"
    }]
},
Run Code Online (Sandbox Code Playgroud)

我想自定义$type属性中的值,使其读取为:

{
    "$type": "Models.Directory.DtoName",
    "id": 67,
    "offices": [{
        "$type": "Models.Directory.AnotherDtoName",
        "officeName": "FOO"
    }]
},
Run Code Online (Sandbox Code Playgroud)

我已经有一个从CamelCasePropertyNamesContractResolver. 我想我需要做的是关闭TypeNameHandling并自己添加自定义属性。我 95% 在那里:

protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
    var assemblyName = type.Assembly.GetName().Name;
    var typeName = type.FullName.Substring(assemblyName.Length + 1);

    var typeProperty = new JsonProperty()
    {
        PropertyName = "$type",
        PropertyType = typeof(string),
        Readable = true,
        Writable = true,
        ValueProvider = null // ????? typeName
    };

    var retval = base.CreateProperties(type, memberSerialization);
    retval.Add(typeProperty);
    return retval;
}
Run Code Online (Sandbox Code Playgroud)

在这一点上,我坚持提供财产的价值。

我不确定这是正确的方法,因为ValueProviderJson.Net 中的每个类型都将 aMemberInfo作为构造函数参数。我不一个MemberInfo供应作为参数,所以....我坚持。

如何添加自定义$type值?由于我不在 C# 中进行反序列化,因此我永远不需要将类型信息转换回类型。

dbc*_*dbc 5

$type您应该创建一个customISerializationBinder和 override ,而不是添加合成属性ISerializationBinder.BindToName。在序列化期间调用此方法以指定TypeNameHandling启用时要发出的类型信息。

例如,以下删除程序集信息以及PROJECTNAME.Api.命名空间的一部分:

public class MySerializationBinder : ISerializationBinder
{
    const string namespaceToRemove = "PROJECTNAME.Api.";

    readonly ISerializationBinder binder;

    public MySerializationBinder() : this(new Newtonsoft.Json.Serialization.DefaultSerializationBinder()) { }

    public MySerializationBinder(ISerializationBinder binder)
    {
        if (binder == null)
            throw new ArgumentNullException();
        this.binder = binder;
    }

    #region ISerializationBinder Members

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        binder.BindToName(serializedType, out assemblyName, out typeName);
        if (typeName != null && typeName.StartsWith(namespaceToRemove))
            typeName = typeName.Substring(namespaceToRemove.Length);

        assemblyName = null;
    }

    public Type BindToType(string assemblyName, string typeName)
    {
        throw new NotImplementedException();
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

然后你可以DtoName用它序列化你的对象,如下所示:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    SerializationBinder = new MySerializationBinder(),
    TypeNameHandling = TypeNameHandling.Objects,
};
var json = JsonConvert.SerializeObject(dto, Formatting.Indented, settings);
Run Code Online (Sandbox Code Playgroud)

笔记:


归档时间:

查看次数:

1000 次

最近记录:

7 年,8 月 前