【问题标题】:Json.NET TypeNameHandling for reading onlyJson.NET TypeNameHandling 只读
【发布时间】:2017-06-22 20:06:47
【问题描述】:

我正在使用以下JsonSerializerSettings

new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.Objects
}

获取或设置序列化程序如何处理类型名称的写入和读取。

我想知道是否有任何方法可以启用类型名称读取,但在写入期间禁用它。

我正在反序列化一个抽象基类列表,因此我需要我的 JSON 上的 $type 节点能够反序列化(使用自定义 SerializationBinder),但我不希望我的响应包含它们的类型和命名空间.

请注意,我指的是 ASP.NET Web API 上下文中的(反)序列化,其中我只能在 Configuration.Formatters 的 JsonFormatter 上的全局级别上设置我的 SerializerSettings控制器级别使用IControllerConfiguration。这些设置始终用于读取和写入。

【问题讨论】:

  • 在创建 Web API 时,请不要使用除 TypeNameHandling.None 之外的其他 TypeNameHandling。使用 TypeNameHandling.Objects 可能会使您的 Web API 易受攻击:alphabot.com/security/blog/2017/net/…
  • @peter 正如文档所述:Incoming types should be validated with a custom SerializationBinder when deserializing with a value other than None. 正如我所提到的那样。

标签: c# json.net


【解决方案1】:

由于这个 TypeNameHandling 只需要特定的 DTO,我刚刚创建了一个自定义 JsonConverter

public class CustomJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(MyDTO);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var customSerializer = new JsonSerializer {
            TypeNameHandling = TypeNameHandling.Objects, 
            Binder = new CustomSerializationBinder()
        };
        return customSerializer.Deserialize(reader, objectType);
    }
}

并在我的JsonFormatter注册:

Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new CustomJsonConverter());

【讨论】:

    【解决方案2】:

    是否使用TypeNameHandling 可以根据SerializeObject/DeserializeObject 进行定义。所以当你不需要$type时不要使用这些设置:

    var typedJson = @"{""$type"":""ConsoleApp2.Program+TestData, ConsoleApp2"",""TestField"":0}";
    var testData = JsonConvert.DeserializeObject(typedJson, new JsonSerializerSettings {
        TypeNameHandling = TypeNameHandling.Objects
    });
    var json = JsonConvert.SerializeObject(testData);    // <----- Notice no settings here
    Console.WriteLine(json);
    
    // Outputs:
    //     {"TestField":0}
    

    【讨论】:

    • 感谢您的回复,但我忘了提及我在 ASP.NET WebAPI 上下文中工作,请参阅我编辑的问题
    猜你喜欢
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多