首页 > 解决方案 > 将 JSON 序列化从 camelCase 更改为 PascalCase [重复 - 没有解决方案?]

问题描述

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

相关链接之一

另一个

我正在使用 .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。ABP 在 .net core 3.0 上工作对我来说不是一个解决方案

我在 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

解决方案


在 .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 ://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?view=netcore-3.1#use-a-custom-json-property-naming-政策


推荐阅读