【问题标题】:Custom Deserialization using Json.NET使用 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 查看我的映射方式stackoverflow.com/questions/40439290/…

标签: c# .net json serialization json.net


【解决方案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 的上下文。
    猜你喜欢
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    相关资源
    最近更新 更多