让ASP.NET端点接受包含未知类型JSON对象的请求

qzwqbdag  于 5个月前  发布在  .NET
关注(0)|答案(2)|浏览(64)

我想接受一个已知类型的对象,其中一个属性只是一个Record<string,any>。目前唯一的方法是强制我的客户端使用JSON。将属性字符串化,然后我就可以很好地将其转换为JSON。问题是,这对我使用过的任何其他框架都没有必要,所以我想允许客户端只传递JSON。
下面是我想要传递的,假设我们有关于系统中特定对象的POST事件:

{
    "eventType" : "created",
    "objectId" : "cb01e673-3835-44a8-a803-7cbfd437f0e2",
    "eventDetails" : 
    {
        "anyKey" : "someValue",
        "someArray" : ["no problem!", "no reason this should not work!"],
        "someNestedObject" : 
        {
            "anyNestedKey" : "should never be an issue"
        }
    }
}

字符串
下面是我的请求对象:

public class ObjectEvent
{  
    public string? ObjectId { get; set; }

    public string? EventType { get; set; }
    public dynamic? EventDetails { get; set; } 
}


问题是,当我得到EventDetails时,它看起来像这样:

Request ValueKind = Object : "{         "whatever": "go for it"     }"


这意味着它现在是一个JsonElement,但这不是真的。它只是一个从客户端传递过来的Json对象。我可以看到那里的对象,但我似乎无法将其带入动态。
同样,如果我强制每个人在POST之前将“EventDetails”属性序列化为字符串,我可以将“dynamic?EventDetails”切换为“string?EventDetails”,并使用Newtonsoft. js,它工作正常,但当人们使用curl和postman访问这个或编写jest测试时,这是不能接受的。他们应该能够传递一个对象,.NET应该接受它,这是一种 *,但不是我可以使用的方式。
有什么建议吗?提前谢谢。

f8rj6qna

f8rj6qna1#

首先,我会质疑API的设计,“什么都可以”是一个好主意。通常有一些限制可以/应该到位(例如嵌套级别)。
另一点:使用dynamic与使用object没有任何区别--除了object在编译时抛出错误的时间点与dynamic在运行时抛出错误的时间点。(如果你有,你可以使用这些知识来定义类,而不是使用dynamic/object)。
无论如何,对于一个建议的解决方案:检查System.Text.Jsondocs,以处理溢出JSON的情况-即任何没有显式定义的情况。(如果你使用的是Newtonsoft.Json,那么要么迁移(基于你使用的.net版本),要么尝试为该库找到等效的方法。
最后,无论如何,你都需要使用JsonElement类。正如你自己编写的那样:

这意味着它现在是一个JsonElement,* 但这不是真的 *。它只是一个从客户端传递过来的Json对象。我可以看到那里的对象,但 * 我似乎无法将其放入动态 *。

粗体文本是true,* 斜体 * 中的文本不是:它是JsonElement,你在dynamic中有它,像这样的代码将工作得很好:

var jsonDetails = (JsonElement)EventDetails;

字符串
或者只是改变类的定义:

public JsonElement? EventDetails { get; set; }

mkshixfv

mkshixfv2#

我想出来了,比看起来简单多了!
假设我有一个RequestModel,然后是一个Model,我试图将数据编组到其中以用于业务逻辑:

public class EventCreateRequest
{ 
    public string? EventType { get; set; }
    public object? EventDetails { get; set; } 
}

public class EventCreateModel
{ 
    public EventTypes EventType { get; set; }
    public ExpandoObject? EventDetails { get; set; } 
}

字符串
然后适配器看起来像这样:

public EventCreateModel convertFromCreateRequestToCreateModel(EventCreateRequest request)
{ 
    EventCreateModel model = new EventCreateModel()
    {
        EventType = request.EventType != null ? Enum.Parse<EventTypes>(request.EventType) : null;
 
        EventDetails = JsonConvert.DeserializeObject<ExpandoObject>(request.EventDetails.ToString(), new ExpandoObjectConverter());
    } 
    return model;
}

相关问题