将不同的JSON反序列化为ASP.NET Core中的类型层次结构

时间:2018-04-12 06:07:54

标签: c# json asp.net-core-2.0 asp.net-core-webapi json-deserialization

在我的ASP.NET 2.0 WebApi中,我确实收到了稍微不同类型的JSON作为POST正文。我可能收到的JSON看起来像这样

{
    "Version": "some string",
    "Session": "somestring",
    "Payload": {}
}

Payload则是以下三种变体之一:

{
    "tmestamp": "string"
}

或者这个:

{
    "tmestamp": "string",
    "name": "string"
}

或者这个:

{
    "tmestamp": "string",
    "status": number,
    "values": [
        number,
        number,
        ...
    ]
}

要创建此层次结构的匹配类型:

public class BaseRequest
{
    public string Version {get;set;}
    public string Session {get;set;}
    public BasePayload Playload {get;set;}
}

public class  BasePayload
{
    public DateTime timestamp {get;set;}
}

public class PayloadVariant1 : BasePayload
{
    public string Name {get;set;}
}

public class PayloadVariant2 : BasePayload
{
    public int Status {get;set;}
    public double[] Values {get;set}
}

JSON格式由第三方供应商定义,因此无法进行调整。我已经按如下方式定义了我的POST方法来获取数据:

[HttpPost]
public void Post([FromBody]BaseRequest content) 

Payload始终为BasePayload,并且无法转换为其他类型,尽管收到的数据包含该内容。因此我想我可能不得不使用泛型并定义几个帖子:

// converted into a generic variant
public class BaseRequest<T> where T : BasePayload 
{
    public string Version {get;set;}
    public string Session {get;set;}
    public T Playload {get;set;}
}

[HttpPost]
public void Post([FromBody]BaseRequest<BasePayload> content) 

[HttpPost]
public void Post([FromBody]BaseRequest<PayloadVariant1> content) 

但后来我得到了这个异常Microsoft.AspNetCore.Mvc.Internal.ActionSelector:Error: Request matched multiple actions resulting in ambiguity. Matching actions: SkillMediator.Controllers.MessagesController.Post (SkillMediator)。我发现可以将Newtonsoft.JSON配置为从JSON读取变量$type,其中包含类型的完全限定名称作为反序列化的提示。但正如已经说过的,JSON来自公共API,我无法改变。

基于给定的JSON格式,我的ASP.NET核心代码中是否有一种完全类型安全的数据结构?

1 个答案:

答案 0 :(得分:1)

您可以将所有差异合并到一个模型类中:

public class BasePayload
{
    public DateTime? timestamp {get;set;}

    public string Name {get;set;}

    public int? Status {get;set;}
    public double[] Values {get;set}
}

但请注意我使用了可空类型,因此与json不匹配的属性将保留为null。