将不同格式的JSON对象反序列化为公共类

时间:2014-11-21 16:16:07

标签: c# json json-deserialization

我有几种包含货币汇率的不同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; }
}

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

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

2 个答案:

答案 0 :(得分:1)

  

注意:这个答案的编写假设您将使用Json.Net。在我发布之后,我意识到你从未在你的问题中特别提到过你正在使用(或想要使用)的串行器。我认为你仍然可以使用与其他序列化器相同的技术,但你可能需要进行调整。 YMMV。

好吧,只要您的映射不重叠,那么一个简单的解决方案就是让您的类中的私有setter使用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

答案 1 :(得分:0)

你在找这样的东西吗?

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

除非我误解了。如果你想要一个“通用”类型使用继承。