繁体   English   中英

如何使用 json.net 自定义反序列化为对象

[英]How to custom deserialize into an object with json.net

我使用http://json2csharp.com/生成了一个代表我的 JSON 的 csharp 类,它工作得非常好。 然而,在与第三方 api 合作一段时间后,我意识到他们的响应并不总是发送相同类型的数据。 我正在查询他们的 API 以获取票证数据,每张票都有一个 SellPrice。 有时,他们将 SellPrice 作为具有货币(字符串)和金额(双倍)的 Money 对象返回,有时他们将其作为双倍发送回来。 所以我试图找到一种优雅地处理这个问题的方法,以便我总是设置我的 SellPrice 对象的数量。 这是当他们将 Money 对象作为 SellPrice 发送时有效的代码的简短版本

public class Ticket
{
    public string Ticket_Id {get; set;}
    //... other fields
    public SellPrice SellPrice {get; set;}
}
public class SellPrice
{
    public string Currency {get; set;}
    public double Amount {get; set;}
}

然后当我得到 Json 时,我像这样反序列化,效果很好......

for (int i = 0; i < jItems.Count; i++)
{
    TUTicket2 item = jItems[i].ToObject<TUTicket2>();
}

...直到我遇到一个返回双精度而不是对象的 API 调用。

所以只是看看它是 Money 对象的情况,我想我会尝试创建一个构造函数,以便我可以根据对象类型设置值,如下所示:

public class SellPrice
{
    public SellPrice(object sellPrice)
    {
        if (sellPrice.GetType() == typeof(Dictionary<string, object>))
        {
            Currency = (string)((Dictionary<string, object>)sellPrice)["Currency"];
            Amount = (double)((Dictionary<string, object>)sellPrice)["Currency"];
        }
    }
    public string Currency { get; set; }
    public double Amount { get; set; }
}

但这不起作用,因为 sellPrice 对象始终为空,所以我想我在那里吠叫错误的树。 有没有办法轻松做到这一点? 我认为我的问题是它自动反序列化为对象类型的方式,但我一直在查看代码/文档并且没有弄清楚我错过了什么。

我在这里有几个目标:我们正在做足够多的 API 工作,我希望能够利用像 json2csharp 这样的工具来生成类。 我还想避免对每个类/对象进行手动反序列化,尽管如果这是我唯一的选择,我可以朝那个方向发展,但当 99% 的值表现正常时,感觉有点矫枉过正。 我也不想根据我进行的 API 调用最终得到每个类的 X 个不同版本。 我试图找到一些解决方案,让我覆盖一小部分而不是所有内容。 对于任何反馈,我们都表示感谢。

您可以通过为您的SellPrice类制作自定义JsonConverter来处理此问题,如下所示:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        SellPrice sellPrice = new SellPrice();
        if (token.Type == JTokenType.Object)
        {
            serializer.Populate(token.CreateReader(), sellPrice);
        }
        else if (token.Type == JTokenType.Float)
        {
            sellPrice.Amount = (double)token;
            // if there is a default currency, set it here, e.g.:
            // sellPrice.Currency = "USD";
        }
        else
        {
            throw new JsonException("Unexpected token type for SellPrice: " + token.Type.ToString());
        }
        return sellPrice;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用它,您需要做的就是向SellPrice类添加一个[JsonConverter]属性,如下所示:

[JsonConverter(typeof(SellPriceConverter))]
public class SellPrice 
{
    ...
}

然后你可以正常反序列化,它应该处理这两种情况。

这里的工作演示: https : //dotnetfiddle.net/qZekyp

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM