.Net Core 3.0.100-preview6 - API Json 响应始终是驼峰式,但我的类不是

问题描述 投票:0回答:5

我有一个 .net core 3.0 预览版 6 MVC 应用程序和 API。 在 API 中,我使用第三方类库(我无法更改),它将类属性定义为 Pascal 格式,并使用 JsonProperty、PropertyName 蛇形格式,例如...

public class Company
{
[JsonProperty(PropertyName = "company_name")]
public string CompanyName { get; set; }

more properties ….
}

问题是,当我通过 api 提供这些内容时,它们会以 Camel 情况(.net core 3 的默认设置)的形式到达 MVC 应用程序...然后无法反序列化回类模型。

无论我尝试什么,API 总是会生成驼峰式的 Json,例如。上面的属性将被称为companyName。

我试过了,

options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver { NamingStrategy = new CamelCaseNamingStrategy { OverrideSpecifiedNames = true } };

options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new DefaultNamingStrategy { OverrideSpecifiedNames = true } };

我已经在camel和默认ContractResolver上尝试过NamingStrategy = null。还尝试将 NamingStrategy 设置为 Snake

但是输出的 Json 没有任何改变,它始终是驼峰式的。

我可以看到,通过在 MVC 应用程序中使用 ReadAsStringAsync,生成的字符串是驼峰式大小写的...当我使用 JsonConvert.DeserializeObject 时,属性始终为 null,因为名称或 Json PropertyName 都与生成的字符串中的名称不匹配。

这是 .net core 预览中的错误还是我遗漏了其他内容?

谢谢 Mustafa,您建议的重复问题与我已经尝试过的解决方案有点相同,即将 ContractResolver / NamingStrategy 的设置更改为不同的值......但是,我的问题是没有建议的解决方案似乎对 API 响应有任何影响,它总是以驼峰命名形式返回。

有趣的是,当我将 NamingStrategy 更改为 Snake 时,Swagger 将模式显示为已设置(即蛇),但实际输出仍然是驼峰式!!!

此外,我无法控制基类,因此我无法更改我尝试传输的类的名称/json 属性。

c# .net-core json.net json-deserialization json-serialization
5个回答
3
投票
Microsoft.AspNetCore.Mvc.NewtonsoftJson

默认不出现。 尝试将此 nuget 包手动安装到您的服务项目中。这对我有用。


1
投票

尝试此操作并删除所有

JsonProperty
属性。

从现在开始,如果您不指定任何

JsonProperty
y,它将像这样
CompanyName
like
company_name
ProPertyName1
like
pro_perty_name1
。在这个例子中将解释属性名称的想法。

并且请务必将此配置添加到

ConfigureServices
方法的底部,它可能会被我不知道的其他内容覆盖。

services.AddMvc().AddJsonOptions(options =>
{
    options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() };
});

0
投票

不太确定问题出在哪里,但感觉这与 Newtonsoft.Json、Json.Net、Swagger 的混合有关,而且我使用 Microsoft.AspNet.WebApi.Client 来获取 HttpContent。 ReadAsAsync….都有不同的 Json

因此,我决定使用 .Net Core 预览版中包含的新 System.Text.Json(而不是其他库)重新开始一个真正简单的应用程序和 api。也不使用 HttpContent.ReadAsAsync,而是将响应作为字符串读取,然后使用新库 (System.Text.Json) 进行反序列化

这样做我遇到了完全相同的问题......属性名称或 Json PropertyName 均不与 api 返回的字符串中的名称匹配,即类属性名称 = "CompanyName" 和 Json PropertyName = "company_name" 以及 api 提供的 json name = "companyName"。因此反序列化时未设置该值。

但是,在新的 System.Text.Json 选项中,我可以指定 PropertyNameCaseInsensitive = true,这解决了我的问题,现在 companyName 等于 CompanyName,并且在反序列化时正确设置了类模型值。

所以我的 api 调用方法最终看起来像这样......

        using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, string.Format("Companies?aCompanyName={0}", aCompanyName));
        using HttpResponseMessage response = await Client.SendAsync(request);
        string content = await response.Content.ReadAsStringAsync();
        if (response.IsSuccessStatusCode == false)
        {
            throw new ApiException
            {
                StatusCode = (int)response.StatusCode,
                Content = content
            };
        }
        _JsonOptions = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        };
        return JsonSerializer.Deserialize<IEnumerable<Company>> (content, _JsonOptions);

我确实尝试在启动类中全局设置 JsonSerializerOptions 但这不起作用。

我已将此方法转移到我的应用程序中的所有 http 调用中,删除了对 Newtonsoft 的所有引用,并且一切正常。


0
投票

我在将 api 从 .netcore 2.2 转换为 .netcore 3 时遇到了这个问题。 即使我的模型是 PascalCase,我的 api 返回的响应也转换为驼峰命名法。 在

startup.cs

.netcore 2:

services.AddMvc()
    .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());

.netcore 3:

// keeps the casing of models when serializing to json (default is converting to camelCase)
services.AddMvc()
    .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null); 

这意味着您不需要导入 newtonsoft.json。


0
投票

试试这个:

builder.Services.AddControllers().AddJsonOptions(jsonOptions => { //防止帕斯卡大小写属性在序列化期间被重命名为驼峰大小写(默认行为) jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null; });

我在 .NET 7.0 中使用它并且它正在工作。

© www.soinside.com 2019 - 2024. All rights reserved.