将 JSON 序列化从 CamelCase 更改为 PascalCase [重复 - 无解决方案?]

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

我知道这与过去的一些问题重复。但没有真正的解决方案。

相关链接之一

另一个

我正在使用 .Net Core 3 多页模板。 我已经尝试了下面给出的一切。但没有用。

这是我的应用程序项目的界面:

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using TSE.Kalibrasyon.Roles.Dto;
using TSE.Kalibrasyon.Users.Dto;

namespace TSE.Kalibrasyon.Labs
{
    public interface ILabAppService : IApplicationService
    {
        string Test();
        Task<List<Entities.Labs.Labs>> GetAllAsync();
        System.Threading.Tasks.Task Update(Entities.Labs.Labs input);
        System.Threading.Tasks.Task Create(Entities.Labs.Labs input);
    }
}

实现是:

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Entities;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.IdentityFramework;
using Abp.Linq.Extensions;
using Abp.Localization;
using Abp.Runtime.Session;
using Abp.UI;
using TSE.Kalibrasyon.Authorization;
using TSE.Kalibrasyon.Authorization.Accounts;
using TSE.Kalibrasyon.Authorization.Roles;
using TSE.Kalibrasyon.Authorization.Users;
using TSE.Kalibrasyon.Roles.Dto;
using TSE.Kalibrasyon.Users.Dto;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using TSE.Kalibrasyon.Entities.Labs.Dto;
using TSE.Kalibrasyon.Entities.Labs;
using TSE.Kalibrasyon.Labs.Dto;
using Abp.Web.Models;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc;

namespace TSE.Kalibrasyon.Labs
{
    //[AbpAuthorize(PermissionNames.Pages_Users)]
    public class LabAppService : KalibrasyonAppServiceBase, ILabAppService
    {
        private readonly IRepository<Entities.Labs.Labs> _labRepository;


        public LabAppService(IRepository<Entities.Labs.Labs> labRepository)
        {
            _labRepository = labRepository;
        }
        [Microsoft.AspNetCore.Mvc.HttpGet]
        public string Test()
        {
            return "merhaba";
        }
        [DontWrapResult]
        public  async Task<List<Entities.Labs.Labs>> GetAllAsync()
        {
            //var chk = await _labRepository.GetAllListAsync();
            return await _labRepository.GetAllListAsync();
        }

        [DontWrapResult]
        //public  List<Entities.Labs.Labs> GetAll2()
        public  object GetAll2()
        {
            List<Entities.Labs.Labs> chk = _labRepository.GetAllListAsync().Result;
            //return _labRepository.GetAllListAsync().Result;
            var bak= new { Items = chk, Count = chk.Count() };
            return new { Items = chk, Count = chk.Count() };
            //return Json(new { Items = chk, Count = chk.Count() }, new JsonSerializerSettings { ContractResolver = new PascalCasePropertyNamesContractResolver() });
        }

        [DontWrapResult]
        public string GetAll3()
        {
            List<Entities.Labs.Labs> chk = _labRepository.GetAllListAsync().Result;
            var obj= new { Items = chk, Count = chk.Count() };
            //return Json(new { Items = chk, Count = chk.Count() }, new JsonSerializerSettings { ContractResolver = new PascalCasePropertyNamesContractResolver() });
            var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
            //var text = JsonConvert.SerializeObject(configuration, settings);
            var text = JsonConvert.SerializeObject(obj);
            return text;
            //return Json(new { Items = chk, Count = chk.Count() });

        }

        public async Task Update(Entities.Labs.Labs input)
        {
            await _labRepository.UpdateAsync(input);
        }
        public async Task Create(Entities.Labs.Labs input)
        {
            await _labRepository.InsertAsync(input);
        }
    }


    //public class Data
    //{
    //    public bool requiresCounts { get; set; }
    //    public int skip { get; set; }
    //    public int take { get; set; }
    //}
}

响应正文为:

[
  {
    "labName": "BASINÇ KALİBRASYON LABORATUVARI",
    "labKod": "BAS",
    "bolgeKodu": 5,
    "id": 1
  }
]

我对该实体的模型是:

using Abp.Domain.Entities;
using Abp.Domain.Repositories;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace TSE.Kalibrasyon.Entities.Labs
{
    [Table("Labs")]
    public partial class Labs : Entity
    {
        private readonly IRepository<Labs> _lablarRepository;
        //private readonly TownAppService _townAppService;
        //private readonly IRepository<Town> _townRepository;
        public Labs()
        {
            //this.Towns = new List<Town>();
            //this.Districts = new List<District>();
            //this.Neighborhoods = new List<Neighborhood>();
            OnCreated();
        }

        //[System.ComponentModel.DataAnnotations.Key]
        //[System.ComponentModel.DataAnnotations.Required()]
        //public virtual int Id
        //{
        //    get;
        //    set;
        //}

        [System.ComponentModel.DataAnnotations.Required()]
        public virtual string LabName
        {
            get;
            set;
        }

        [System.ComponentModel.DataAnnotations.StringLength(3)]
        [System.ComponentModel.DataAnnotations.Required()]
        public virtual string LabKod
        {
            get;
            set;
        }

        [System.ComponentModel.DataAnnotations.Required()]
        public virtual int BolgeKodu
        {
            get;
            set;
        }





        #region Extensibility Method Definitions

        partial void OnCreated();

        #endregion
    }
}

还有另一个大问题,我使用 Syncfusion .Net Core Grid 作为第三方工具。它需要一种数据库操作方法,如下所示。

[IgnoreAntiforgeryToken]
        public IActionResult UrlDatasource([FromBody]DataManagerRequest dm)
        {
            Api api=new Api();

            //IEnumerable DataSource = Orders.GetAllRecords();
            IEnumerable DataSource = api.LabsGetAll();
            DataOperations operation = new DataOperations();


            if (dm.Search != null && dm.Search.Count > 0)
            {
                DataSource = operation.PerformSearching(DataSource, dm.Search);  //Search
            }
            if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
            {
                DataSource = operation.PerformSorting(DataSource, dm.Sorted);
            }
            if (dm.Where != null && dm.Where.Count > 0) //Filtering
            {
                DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);



            }
            int count = DataSource.Cast<Entities.Labs.Labs>().Count();
            if (dm.Skip != 0)
            {
                DataSource = operation.PerformSkip(DataSource, dm.Skip);         //Paging
            }
            if (dm.Take != 0)
            {
                DataSource = operation.PerformTake(DataSource, dm.Take);
            }
            return dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource);
        }

当我不使用 [IgnoreAntiforgeryToken] 方法时。它不会命中带有 HTTP ERROR 415 的方法。

Syncfusion 表示,这只是因为骆驼外壳并提供添加

services.PostConfigure<MvcJsonOptions>(options =>
{
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();
}); 

进入StartUp文件的ConfigureServices方法。但我认为它仅适用于 .net core 2.x。这对我来说不是一个在 .net core 3.0 上工作的 ABP 的解决方案

我的 Host App 中的 StartUp.cs 是:

using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Castle.Facilities.Logging;
using Abp.AspNetCore;
using Abp.AspNetCore.Mvc.Antiforgery;
using Abp.Castle.Logging.Log4Net;
using Abp.Extensions;
using TSE.Kalibrasyon.Configuration;
using TSE.Kalibrasyon.Identity;
using Abp.AspNetCore.SignalR.Hubs;
using Abp.Dependency;
using Abp.Json;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Mvc;

namespace TSE.Kalibrasyon.Web.Host.Startup
{
    public class Startup
    {
        private const string _defaultCorsPolicyName = "localhost";

        private readonly IConfigurationRoot _appConfiguration;

        public Startup(IWebHostEnvironment env)
        {
            _appConfiguration = env.GetAppConfiguration();
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            //MVC
            services.AddControllersWithViews(
                options =>
                {
                    options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute());
                }
            ).AddNewtonsoftJson(options =>
            {
                //options.SerializerSettings.ContractResolver = new AbpMvcContractResolver(IocManager.Instance)
                //{
                //    NamingStrategy = new CamelCaseNamingStrategy()
                //};
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            });


            services.PostConfigure<MvcNewtonsoftJsonOptions>(options =>
            {
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            });



            IdentityRegistrar.Register(services);
            AuthConfigurer.Configure(services, _appConfiguration);

            services.AddSignalR();

            // Configure CORS for angular2 UI
            services.AddCors(
                options => options.AddPolicy(
                    _defaultCorsPolicyName,
                    builder => builder
                        .WithOrigins(
                            // App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
                            _appConfiguration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials()
                )
            );

            // Swagger - Enable this line and the related lines in Configure method to enable swagger UI
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo() { Title = "Kalibrasyon API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);

                // Define the BearerAuth scheme that's in use
                options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                });
            });

            // Configure Abp and Dependency Injection
            return services.AddAbp<KalibrasyonWebHostModule>(
                // Configure Log4Net logging
                options => options.IocManager.IocContainer.AddFacility<LoggingFacility>(
                    f => f.UseAbpLog4Net().WithConfig("log4net.config")
                )
            );
        }

        public void Configure(IApplicationBuilder app,  ILoggerFactory loggerFactory)
        {
            app.UseAbp(options => { options.UseAbpRequestLocalization = false; }); // Initializes ABP framework.

            app.UseCors(_defaultCorsPolicyName); // Enable CORS!

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAbpRequestLocalization();


            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<AbpCommonHub>("/signalr");
                endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapControllerRoute("defaultWithArea", "{area}/{controller=Home}/{action=Index}/{id?}");
            });

            // Enable middleware to serve generated Swagger as a JSON endpoint
            app.UseSwagger();
            // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint(_appConfiguration["App:ServerRootAddress"].EnsureEndsWith('/') + "swagger/v1/swagger.json", "Kalibrasyon API V1");
                options.IndexStream = () => Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("TSE.Kalibrasyon.Web.Host.wwwroot.swagger.ui.index.html");
            }); // URL: /swagger
        }
    }
}

有您可能知道的解决方案吗?预先感谢。

还有,使用 JsonResult 控制属性名称的序列化。但没有用。请问有什么办法吗?

aspnetboilerplate
4个回答
6
投票

在 .NET Core 3.x 中,您现在需要修改

JsonSerializerOptions.PropertyNamingPolicy

对于 PascalCase — 按照您的原始属性名称 — 设置为

null
:

services.AddMvc(...)
    .AddJsonOptions(jsonOptions =>
    {
        jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

对于小写字母(或其他自定义命名策略),子类

JsonNamingPolicy
并覆盖
ConvertName
方法。

services.AddMvc(...)
    .AddJsonOptions(jsonOptions =>
    {
        jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = new JsonLowercaseNamingPolicy();
    });
public class JsonLowercaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name) => name.ToLowerInvariant();
}

参考:https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?view=netcore-3.1#use-a-custom-json-property-命名策略


5
投票

在 .NET 6.0 中,我设法解决了同样的问题,只需在 Program.cs 中添加此代码(ofc,之前安装了 Newtonsoft 软件包。):

builder.Services.AddControllers().AddJsonOptions(options => 
options.JsonSerializerOptions.PropertyNamingPolicy = null);

1
投票

对于newtonsoft来说,这就是实现。

.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ContractResolver = null;
}
);

希望有帮助。


0
投票

对于其他读者,尝试弄清楚如何在 ASP.NET Core 7.0 中执行此操作。看起来,使用新 Result 方法(例如

Results.Ok(obj)
)的 API 响应的 JSON 序列化不尊重使用 AddControllers 设置的全局序列化器选项。

相反,您可以将 jsonOptions 传递给

Result.Json
,如下所示:

app.MapGet("/", () =>
{
    var jsonOptions = new JsonSerializerOptions
    {
        PropertyNamingPolicy = null
    };

    return Results.Json(
        new { Hello = "World" },
        jsonOptions,
        statusCode: (int?)HttpStatusCode.OK);
});

这可以提取到实用方法中

public static class ResultExtensions
{
    public static IResult OkPascalCase<T>(this T obj)
    {
        var options = new JsonSerializerOptions
        {
            PropertyNamingPolicy = null
        };
        return Results.Json(obj, options, statusCode: (int?)HttpStatusCode.OK);
    }
}
app.MapGet("/", () =>
{
    return ResultExtensions.OkPascalCase(new { Hello = "World" });
});
© www.soinside.com 2019 - 2024. All rights reserved.