简体   繁体   English

当事先不知道 object 类型时,如何反序列化 JSON?

[英]How can I deserialize JSON when the object type is not known beforehand?

So I have an API and front-end that I am developing, and I need a way to deserialize JSON when one of the values could be a List of multiple different types.所以我有一个 API 和我正在开发的前端,我需要一种方法来反序列化 JSON 当其中一个值可能是多个不同类型的列表时。 Currently I'm deserializing it into a List<dynamic> but that's a huge pain to work with in my context.目前我正在将其反序列化为List<dynamic>但在我的上下文中使用它是一个巨大的痛苦。

public class WorkbenchAPI   
{
    public string status { get; set; }
    public HttpStatusCode code { get; set; }
    public string error { get; set; }
    public string guid { get; set; }
    public List<dynamic> results { get; set; }
}

Sample JSON样品 JSON

{
    "status": "ok",
    "code": 200,
    "error": null,
    "guid": "1234",
    "results": [
        {
            "SamAccountName": "dizbuster",
            "CN": "Buster, Diz",
            "EmailAddress": "dizbuster@whatever.com",
        }
    ]
}

In the above example JSON, results should be deserialized into type List<ClassA> for example.在上面的示例 JSON 中,例如,结果应反序列化为List<ClassA>类型。

{
    "status": "ok",
    "code": 200,
    "error": null,
    "guid": "1234",
    "results": [
        {
            "data": "127.0.0.1",
            "owner": "dizbuster",
            "email": "dizbuster@whatever.com",
        },
        {
            "data": "192.168.0.1",
            "owner": "dizbuster",
            "email": "dizbuster@whatever.com",
        }
    ]
}

Where as in this sample, results should be deserialized into List<ClassB> .在此示例中,结果应反序列化为List<ClassB>

Some of the field names may show up in different types, but some are not.一些字段名称可能会以不同的类型显示,但有些则不会。 Functionally they are two different types representing the outputs from two separate API calls, so I'd like to have it deserialize into specific object types as opposed to using dynamic or a monolithic object that contains every possible field.从功能上讲,它们是两种不同的类型,表示来自两个单独的 API 调用的输出,所以我想让它反序列化为特定的 object 类型,而不是使用包含每个可能字段的dynamic或单片 ZA8CFDE6331BD59EB2AC96F8911C4B6666。

Currently I'm taking the List<dynamic> and serializing it back into a temporary JSON string, then deserializing it again into the List<ClassA> or whatever.目前,我正在将List<dynamic>序列化回临时 JSON 字符串,然后将其再次反序列化为List<ClassA>或其他任何内容。 This seems like a bad way to do it, and is cumbersome to work with.这似乎是一种不好的方法,并且使用起来很麻烦。

Is there a better way to structure this or to handle the serialization/deserialization?有没有更好的方法来构造它或处理序列化/反序列化? I have full control over both ends so it's not too difficult for me to alter the JSON as well if needed.我可以完全控制两端,因此如果需要,我也可以轻松更改 JSON。 Also, I know that a particular API call will return JSON that looks like this, while another API call will return JSON that looks like that. Also, I know that a particular API call will return JSON that looks like this, while another API call will return JSON that looks like that. Each case should result in a differently typed list每个案例都应该产生一个不同类型的列表

Since you know in advance what type of data is being returned in "results" for each API call, you can make your WorkbenchAPI class generic:由于您事先知道每个 API 调用的"results"中返回的数据类型,您可以使WorkbenchAPI class 通用:

public abstract class WorkbenchAPI
{
    protected abstract IReadOnlyCollection<dynamic> GetResults();

    public string status { get; set; }
    public HttpStatusCode code { get; set; }
    public string error { get; set; }
    public string guid { get; set; }
    public IReadOnlyCollection<dynamic> results => GetResults();
}

public class WorkbenchAPI<T> : WorkbenchAPI where T : class
{
    protected override IReadOnlyCollection<dynamic> GetResults() => results;
    public new List<T> results { get; set; } = new List<T>();
}

Notes:笔记:

  • I extracted the common properties into an abstract base class to allow them to be accessed by pre-existing non-generic code that does not care about the specific type of result.我将公共属性提取到抽象基础 class 中,以允许通过不关心特定结果类型的预先存在的非泛型代码访问它们。

  • I also added a IReadOnlyCollection<dynamic> results to the base class to ease integration with pre-existing code, eg:我还在基础 class 中添加了IReadOnlyCollection<dynamic> results ,以简化与预先存在的代码的集成,例如:

     // Deserialize to the concrete, known type var root = JsonConvert.DeserializeObject<WorkbenchAPI<ClassA>>(json); // Access the results in a type-safe manner: var accounts = root.results.Select(r => r.SamAccountName).ToList(); // Upcast to the base class in code where we don't need to know about the specific result type. // Eg: accessing root properties like guid or getting the result count. WorkbenchAPI baseRoot = root; var count = baseRoot.results.Count; var guid = baseRoot.guid;

    However, adding access to the results as a non-generic read-only collection of dynamic objects is optional, and could be removed if your legacy code can be rewritten to be generic.但是,作为dynamic对象的非泛型只读集合添加对结果的访问是可选的,如果您的旧代码可以重写为泛型,则可以将其删除。

Demo fiddle here: https://dotnetfiddle.net/lbTs1z演示小提琴在这里: https://dotnetfiddle.net/lbTs1z

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

相关问题 如何在不事先知道类型的情况下使用XmlSerializer反序列化可能是基类或派生类的对象? - How do I use an XmlSerializer to deserialize an object that might be of a base or derived class without knowing the type beforehand? 无法将 Json 对象反序列化为类型 - can not deserialize Json Object to Type 当派生类型事先未知时,使用DataContractSerializer反序列化派生类型 - Deserializing derived type using DataContractSerializer when derived type is not known beforehand 反序列化JSON-如何反序列化此JSON? - Deserialize JSON - How can I deserialize this JSON? 如何基于数据中的属性值选择一个对象类型以使用Json.Net反序列化 - How can I select an object type to deserialize using Json.Net based on property values in the data 如何将 json object 反序列化为 json 字符串? - How can I deserialize a json object into a json string? 如何将 json 字典反序列化为其原始对象类型? - How would I deserialize a json dictionary to its original object type? 如何将json对象反序列化为复杂对象? - How can I deserialize a json object into a complex object? 无法将 json 对象反序列化为模型类类型 - Can not Deserialize json object to model class type 如何在编译时不知道对象类型时如何构建LINQ查询 - How can I build LINQ query when object type is not known at compile-time
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM