将反序列化对象转换为另一种类型

时间:2018-06-18 06:56:53

标签: c# json json.net

我正在调用API,为所有操作返回标准响应结构。我使用Newtonsoft.Json和JsonConvert.DeserializeObject<Response>

对响应进行反序列化
 public class Response
 {
    public int Code { get; set; }

    public string Message { get; set; }

    public object Result { get; set; }

    public DateTime ResponseDateTime { get; set; }
 }

Result对象的更改取决于已请求的请求操作以及是否存在错误(Code + Message描述错误)。我知道Result对象的结构,并为我需要的每个Result创建了类。

如何将Result对象转换为类型变量,例如Detail[]?我知道我可以序列化Result对象并再次反序列化,但肯定有一个更优雅的解决方案。

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

    public string DetailOne { get; set; }

    public string DetailTwo { get; set; }
 }

2 个答案:

答案 0 :(得分:4)

如果你总是知道你会得到什么样的Result,我建议Response通用:

public class Response<TResult>
{
    public int Code { get; set; }
    public string Message { get; set; }
    public T Result { get; set; }
    public DateTime ResponseDateTime { get; set; }
}

然后你可以反序列化到Response<Detail[]>,Json.NET应该处理好一切。

这假设如果出现错误,您将无法获得可能存在问题的Result。或者,您仍然可以反序列化为Response类,但具有JToken属性类型:

public class Response
{
    public int Code { get; set; }
    public string Message { get; set; }
    public JToken Result { get; set; }
    public DateTime ResponseDateTime { get; set; }
}

然后使用:

Response response = JsonConvert.DeserializeObject<Response>(json);
if (response.Code == 200) // Or whatever
{
    Detail[] details = response.Result.ToObject<Detail[]>();
}

您可以将其包装到通用方法中。我首先至少尝试通用响应类。

答案 1 :(得分:1)

如果您将对象模型更改为:

public class Response<T>
{
    public int Code { get; set; }
    public string Message { get; set; }
    public T Result { get; set; }
    public DateTime ResponseDateTime { get; set; }
}

public class Detail
{
    public int Id { get; set; }
    public string DetailOne { get; set; }
    public string DetailTwo { get; set; }
}

然后你可以这样做:

var original = new Response<Detail>()
{
    Code = 42,
    Message = "OK",
    Result = new Detail()
    {
        Id = 1701,
        DetailOne = "Don't",
        DetailTwo = "Panic",
    },
    ResponseDateTime = DateTime.Now,
};

var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);

var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);

if (response.Code == 42)
{
    Detail detail = response.Result.ToObject<Detail>();

    /* Do something with `Detail`. */
}

这似乎是一种非常好的方法来获取基础Detail对象。

关键技术是序列化Response<Detail>并反序列化为Response<JToken>。简单。

当然,如果你真的想创建一个Response<Detail>实例,你可以通过直接的字段到字段映射,以一种相当直接的方式从Response<JToken>转换为Response<Detail>

以下是代码的Response<Detail[]>版本:

var original = new Response<Detail[]>()
{
    Code = 42,
    Message = "OK",
    Result = new Detail[]
    {
        new Detail()
        {
            Id = 1701,
            DetailOne = "Don't",
            DetailTwo = "Panic",
        },
        new Detail()
        {
            Id = 360,
            DetailOne = "Microsoft",
            DetailTwo = "Xbox",
        }
    },
    ResponseDateTime = DateTime.Now,
};

var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);

var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);

if (response.Code == 42)
{
    Detail[] detail = response.Result.ToObject<Detail[]>();

    /* Do something with `Detail[]`. */
}