【问题标题】:Deserialize JSON objects in differents formats to a common class将不同格式的 JSON 对象反序列化为通用类
【发布时间】:2014-11-21 16:16:07
【问题描述】:

我从几个包含货币汇率的不同 HTTP API 得到结果。 结果非常相似,但不幸的是它们并不完全相同。

我想将它们反序列化为一个具有固定通用类型的对象。 我想有比手动篡改字符串更好的方法。

有什么想法吗?

编辑:

假设:

-来自API1的结果我得到:

field_1, field_2, field_3

-来自API2的结果我得到:

field_1, field_2, field_007,

-来自API3的结果我得到:

field_111, field_2, field_3,

我想反序列化结果的类如下所示:

class DeserializedJson
{
    public string field_1 { get; set; }
    public string field_2 { get; set; }
    public string field_3 { get; set; }
}

此示例中的重点:来自DeserializedJson 对象的field_3 只能显示为field_3field_007。这两个选项。

所以我只是想知道是否有条件反序列化属性或类似的东西?

【问题讨论】:

  • 如何确定 JSON 中的哪个“field_xxx”值映射到您类中的哪个字段?
  • @BrianRogers 请看我的更新。 field_xxx 可以以严格指定的形式出现。
  • 您使用的是哪个序列化程序?
  • @Grx70 我没有序列化程序。这些数据来自外部 HTTP API
  • 我的意思是你使用哪个序列化器来反序列化数据?

标签: c# json json-deserialization


【解决方案1】:

注意:此答案是假设您将使用Json.Net 编写的。发布后,我意识到您从未在问题中具体提及您正在使用(或想要使用)的序列化程序。我认为您仍然可以将此处介绍的相同技术用于其他序列化程序,但您可能需要进行调整。 YMMV。

好吧,只要您的映射不重叠,那么一个简单的解决方案是在您的类中使用私有设置器供 Json.Net 使用,这将设置正确的公共属性。这是因为 Json.Net 将忽略不在 JSON 中的类成员。如果您采用这种方法,修改后的类如下所示:

class DeserializedJson
{
    public string field_1 { get; set; }
    public string field_2 { get; set; }
    public string field_3 { get; set; }
    [JsonProperty]
    private string field_007 
    {
        set { field_3 = value; }
    }
    [JsonProperty]
    private string field_111 
    {
        set { field_1 = value; }
    }
}

这里有一个演示来证明这是可行的:

class Program
{
    static void Main(string[] args)
    {
        DeserializeAndDump(1, @"{""field_1"":""a"",""field_2"":""b"",""field_3"":""c""}");
        DeserializeAndDump(2, @"{""field_1"":""d"",""field_2"":""e"",""field_007"":""f""}");
        DeserializeAndDump(3, @"{""field_111"":""g"",""field_2"":""h"",""field_3"":""i""}");
    }

    private static void DeserializeAndDump(int n, string json)
    {
        Console.WriteLine("--- API " + n + " ---");
        DeserializedJson obj = JsonConvert.DeserializeObject<DeserializedJson>(json);
        Console.WriteLine("field_1: " + obj.field_1);
        Console.WriteLine("field_2: " + obj.field_2);
        Console.WriteLine("field_3: " + obj.field_3);
        Console.WriteLine();
    }
}

输出:

--- API 1 ---
field_1: a
field_2: b
field_3: c

--- API 2 ---
field_1: d
field_2: e
field_3: f

--- API 3 ---
field_1: g
field_2: h
field_3: i

当然,如果 JSON 中的 field_007 有时映射到您的班级中的 field_3 和有时映射到 field_2,则此方法将不起作用。如果是这种情况,那么您需要为每个不同的 API 方法创建一个单独的“DeserializedJson”类。您可以让它们都继承自同一个基类,并在每个子类中使用上述技术在基类中设置正确的属性。这就是它的样子:

class DeserializedJson
{
    public string field_1 { get; set; }
    public string field_2 { get; set; }
    public string field_3 { get; set; }
}

class DeserializedJsonAPI1 : DeserializedJson
{
    [JsonProperty]
    private string field_007
    {
        set { field_2 = value; }
    }
}

class DeserializedJsonAPI2 : DeserializedJson
{
    [JsonProperty]
    private string field_007
    {
        set { field_3 = value; }
    }
}

演示:

class Program
{
    static void Main(string[] args)
    {
        DeserializeAndDump<DeserializedJsonAPI1>(1, @"{""field_1"":""q"",""field_007"":""r"",""field_3"":""s""}");
        DeserializeAndDump<DeserializedJsonAPI2>(2, @"{""field_1"":""x"",""field_2"":""y"",""field_007"":""z""}");
    }

    private static void DeserializeAndDump<T>(int n, string json) where T : DeserializedJson
    {
        Console.WriteLine("--- API " + n + " ---");
        DeserializedJson obj = JsonConvert.DeserializeObject<T>(json);
        Console.WriteLine("field_1: " + obj.field_1);
        Console.WriteLine("field_2: " + obj.field_2);
        Console.WriteLine("field_3: " + obj.field_3);
        Console.WriteLine();
    }
}

输出:

--- API 1 ---
field_1: q
field_2: r
field_3: s

--- API 2 ---
field_1: x
field_2: y
field_3: z

【讨论】:

    【解决方案2】:

    你在寻找这样的东西吗?

    (YourClass)Newtonsoft.Json.JsonConvert.DeserializeObject(response, typeof(YourClass));
    

    除非我有误解。如果您想要“通用”类型,请使用继承。

    【讨论】:

    • 也许是这样的? public static dynamic Convert(dynamic source, Type dest) { return Convert.ChangeType(source, dest); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-17
    • 2017-12-19
    相关资源
    最近更新 更多