如何实现可用于反序列化多级json的class?

How to implement class which can be used to de-serialize multiple level json?

我有一个 json 字符串,例如:

{
    "sn_request": {
        "sn_body": {
            "getExtensionlink": {
                "pid": null,
                "productUrl": "https://xx",
                "promotionId": null,
                "quanUrl": null,
                "subUser": null,
                "sugsUrl": null
            }
        }
    }
}

由于节点 getExtensionlink 是动态的,我实现 class 如下所示:

public class SnRequest<T>
{
    public T sn_body { get; set; }
}

public class Root<T>
{
    public SnRequest<T> sn_request { get; set; }
}

public class GetExtensionlink<T>
{
    public T getExtensionlink { get; set; }
}

public class GetExtensionlinkTest
{
    [JsonProperty("pid")]
    public string Pid { get; set; }
    [JsonProperty("productUrl")]

    public string ProductUrl { get; set; }
    [JsonProperty("promotionId")]

    public string PromotionId { get; set; }
    [JsonProperty("quanUrl")]

    public string QuanUrl { get; set; }
    [JsonProperty("subUser")]

    public string SubUser { get; set; }
    [JsonProperty("sugsUrl")]

    public string SugsUrl { get; set; }
}

然后,通过下面的代码反序列化它:

var getExtensionlinkT = new GetExtensionlinkTest
{
    ProductUrl = @"https://m.suning.com/product/0071237944/000000012059477830.html?utm_campaign=1608091212288684183&utm_source=share-copyurl&utm_medium=2cd5ed46-copyurl"
};

var root = new Root<GetExtensionlink<GetExtensionlinkTest>>
{
    sn_request = new SnRequest<GetExtensionlink<GetExtensionlinkTest>>
    {
        sn_body = new GetExtensionlink<GetExtensionlinkTest>
        {
            getExtensionlink = getExtensionlinkT
        }                    
    }
};

var result = await client.PostAsJsonAsync<Root<GetExtensionlink<GetExtensionlinkTest>>, TestResponseBase<GetExtensionlink<GetExtensionlinkResponse>>>(@"https://xx", root);
            

但是,这一行Root<GetExtensionlink<GetExtensionlinkTest>让人有点难以接受。

我希望是否有任何方法可以使上面的代码干净和可重用。

使用 JObject 怎么样?

简化示例

class Root
{
    public JObject Body { get; set; }
}

class X
{
    public int Id { get; set; }
}

class Y
{
    public string Desc { get; set; }
}

所以我有一个顶级实体和 2 个不同的子实体。

序列化

var a = new Root { Body = JObject.FromObject(new X {Id = 1}) };
var b = new Root { Body = JObject.FromObject(new Y {Desc = "Test"}) };

var jsonA = JsonConvert.SerializeObject(a);
var jsonB = JsonConvert.SerializeObject(b);

Console.WriteLine(jsonA);
Console.WriteLine(jsonB);

这里我们使用FromObject将子实体转换为JObject

输出

{"Body":{"Id":1}}
{"Body":{"Desc":"Test"}}

反序列化

var rootA = JsonConvert.DeserializeObject<Root>(jsonA);
var rootB = JsonConvert.DeserializeObject<Root>(jsonB);

var x = rootA.Body.ToObject<X>();
var y = rootB.Body.ToObject<Y>();

Console.WriteLine(x.Id);
Console.WriteLine(y.Desc);

这里我们使用ToObjectJObjects子实体转换成。


使用这种方法,您无需一直向下传递通用参数。