使用 Json.NET 自定义反序列化

Posted

技术标签:

【中文标题】使用 Json.NET 自定义反序列化【英文标题】:Custom Deserialization using Json.NET 【发布时间】:2017-03-19 06:26:27 【问题描述】:

我有课

public class Order

   public int Id  get; set; 
   public string ShippingMethod  get; set; 

我想将下面的 JSON 数据反序列化到上面的类/对象中

string json = @"
  'Id': 1,
  'ShippingMethod': 
     'Code': 'external_DHLExpressWorldwide',
     'Description': 'DHL ILS Express Worldwide'
  
";

我的想法是 JSON 中的 ShippingMethod 是一个对象,但我只想到达 ShippingMethod.Code(在 JSON 中),它将在反序列化期间作为 stringOrder 类中传递给 ShippingMethod

我怎样才能使用Json.NET 实现这个目标?

我相信我可以使用CustomJsonConverter 来完成它。但我很困惑。文档中的示例仅适用于 WriteJson,但不适用于 ReadJson

【问题讨论】:

所以CodeDescriptionShippingMethod 里面?如何序列化? 你只需要“Id”和“Code”在同一级别? 是的,这是我的问题,也是我想要完成的目标 ShippingMethod 是 json 中的对象和 C# 类中的字符串。你怎么能映射这个。您必须按如下方式更改代码。 @Aruna 查看我的映射方式***.com/questions/40439290/… 【参考方案1】:

我只是使用JsonConverter 解决我的问题,正如我在上面的问题中提到的那样。下面是我的完整代码:

public class Order

    public int Id  get; set; 

    [JsonConverter(typeof(ShippingMethodConverter))]
    public string ShippingMethod  get; set; 


public class ShippingMethodConverter : JsonConverter


    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        throw new NotImplementedException("Not implemented yet");
    

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.Null)
        
            return string.Empty;
         
        else if (reader.TokenType == JsonToken.String)
        
            return serializer.Deserialize(reader, objectType);
        
        else
        
            JObject obj = JObject.Load(reader);
            if (obj["Code"] != null) 
                return obj["Code"].ToString();
            else 
                return serializer.Deserialize(reader, objectType);
        
    

    public override bool CanWrite
    
        get  return false; 
    

    public override bool CanConvert(Type objectType)
    
        return false;
    

【讨论】:

【参考方案2】:
 dynamic o = JsonConvert.DeserializeObject(json);
 var order = new Order
 
     Id = o.Id,
     ShippingMethod = o.ShippingMethod.Code
 ;

将对象反序列化为动态对象,然后通过访问动态对象属性来填充Order 对象

【讨论】:

这个+1。我认为这是没有属性污染和新类创建的最佳清洁方式:) 谢谢你的回答,但是如果有很多其他属性就不适合了 你还没有说还有更多的属性需要管理。为了解决这个问题,你可以添加一个映射一次的扩展方法,然后你可以在任何你想要的地方使用它。但是你的解决方案似乎还可以,只是两个属性的代码行(在我看来) 是的,看起来有很多代码,但实际上它会让你的模型保持干净。【参考方案3】:

您可以使用JsonPropertyJsonIgnore 属性来指导反序列化过程...所以您的模型可以是:

public class Order

    public int Id  get; set; 

    [JsonIgnore]
    public string ShippingMethod
    
        get
        
            return (string)TempShippingMethod?["Code"];
        
    

    [JsonProperty("ShippingMethod")]
    private JObject TempShippingMethod  set; get; 


var res = JsonConvert.DeserializeObject<Order>(json);

【讨论】:

是的,这只是一个小技巧。我不喜欢这种方式,但我赞成 :) 尊重你的回答 @Habibillah 我也不喜欢你的回答,对于一个简单的事情来说太麻烦了,但我尊重你的意见,我发布了我的回答的简化版本.. 不用担心 :)。问题很简单,但我的真实想法是,有很多属性和糟糕的 json 架构,它真的很值得。例子。保存订单,您必须传递字符串,但要获取订单详细信息,您需要一个对象。还有更多 我不同意这是一个 hack。 JsonIgnore 就是为这种目的而设计的——这意味着您不必重新编写序列化。据推测,我们缺少一些关于为什么这不适合 OP 的上下文。

以上是关于使用 Json.NET 自定义反序列化的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Json.Net 序列化/反序列化具有附加属性的自定义集合

如何使用 Json.Net 序列化/反序列化带有自定义键的字典?

JSON.Net无法在自定义JsonConverter中反序列化json数组

如何使用 Json.NET 反序列化高精度十进制值?

c# 通过json.net中的JsonConverter进行自定义序列化与反序列化

json.net中属性的自定义反序列化[重复]