ASP.NET Core 3.1系列(30)——Newtonsoft.Json实现JSON的序列化和反序列化

32 篇文章 42 订阅

1、前言

在早期版本的ASP.NET Core项目中,Newtonsoft.Json的使用率非常高。虽然微软当前主推System.Text.Json来处理JSON的序列化和反序列化,但Newtonsoft.Json在这方面做的也是相当不错,下面就来介绍一下它的用法。

2、引入Newtonsoft.Json

新建一个Web API项目,使用NuGet引入如下组件:

Microsoft.AspNetCore.Mvc.NewtonsoftJson

在这里插入图片描述
新建一个实体类Person,代码如下:

using System;

namespace App
{
    public class Person
    {
        public int Id { get; set; }
        public string PersonName { get; set; }
        public string PersonGender { get; set; }
        public DateTime? BirthOfDate { get; set; }
    }
}

新建一个控制器PersonController,添加一个Get方法,代码如下:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace App.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        [HttpGet]
        public JsonResult Get()
        {
            List<Person> list = new List<Person>
            {
                new Person { Id = 1, PersonName = "张三", PersonGender = "男", PersonAge = 30 },
                new Person { Id = 2, PersonName = "李四", PersonGender = "女", PersonAge = 31 },
                new Person { Id = 3, PersonName = "王五", PersonGender = "男", PersonAge = 32 }
            };
            return new JsonResult(list);
        }
    }
}

运行结果如下所示:

[{"id":1,"personName":"\u5F20\u4E09","personGender":"\u7537","birthOfDate":"2000-01-01T00:00:00"},{"id":1,"personName":"\u674E\u56DB","personGender":"\u5973","birthOfDate":"2000-02-02T00:00:00"},{"id":1,"personName":"\u738B\u4E94","personGender":"\u7537","birthOfDate":"2000-03-03T00:00:00"}]

与之前一样,这里存在中文乱码、时间格式等等,下面就来说一说如何在Newtonsoft.Json中去设置它们。

3、序列化操作

3.1、JSON数据编码

这里与System.Text.Json需要指定编码格式不同,我们只需要指定Newtonsoft.Json为全局序列化的工具即可,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {

            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

运行结果如下所示,可以发现中文编码正确。

[{"id":1,"personName":"张三","personGender":"男","birthOfDate":"2000-01-01T00:00:00"},{"id":2,"personName":"李四","personGender":"女","birthOfDate":"2000-02-02T00:00:00"},{"id":3,"personName":"王五","personGender":"男","birthOfDate":"2000-03-03T00:00:00"}]

3.2、JSON文本格式化

如果希望将输出的JSON文本格式化,可以对Formatting进行设置,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

运行结果如下所示:

[
  {
    "id": 1,
    "personName": "张三",
    "personGender": "男",
    "birthOfDate": "2000-01-01T00:00:00"
  },
  {
    "id": 2,
    "personName": "李四",
    "personGender": "女",
    "birthOfDate": "2000-02-02T00:00:00"
  },
  {
    "id": 3,
    "personName": "王五",
    "personGender": "男",
    "birthOfDate": "2000-03-03T00:00:00"
  }
]

3.3、JSON字段命名格式

如果你希望采用驼峰式命名,可以设置ContractResolverCamelCasePropertyNamesContractResolver,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;

                // 驼峰式命名
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

运行结果如下所示:

[
  {
    "id": 1,
    "personName": "张三",
    "personGender": "男",
    "birthOfDate": "2000-01-01T00:00:00"
  },
  {
    "id": 2,
    "personName": "李四",
    "personGender": "女",
    "birthOfDate": "2000-02-02T00:00:00"
  },
  {
    "id": 3,
    "personName": "王五",
    "personGender": "男",
    "birthOfDate": "2000-03-03T00:00:00"
  }
]

如果你希望采用帕斯卡命名,可以设置ContractResolverDefaultContractResolver,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;

                // 帕斯卡命名
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

运行结果如下所示:

[
  {
    "Id": 1,
    "PersonName": "张三",
    "PersonGender": "男",
    "BirthOfDate": "2000-01-01T00:00:00"
  },
  {
    "Id": 2,
    "PersonName": "李四",
    "PersonGender": "女",
    "BirthOfDate": "2000-02-02T00:00:00"
  },
  {
    "Id": 3,
    "PersonName": "王五",
    "PersonGender": "男",
    "BirthOfDate": "2000-03-03T00:00:00"
  }
]

3.4、忽略JSON中的null值

如果希望忽略null值,可设置NullValueHandling属性,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;

                // 驼峰式命名
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

                // 忽略null值
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

修改一下PersonController,将BirthOfDate设置为null,代码如下:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace App.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        [HttpGet]
        public JsonResult Get()
        {
            List<Person> list = new List<Person>
            {
                new Person { Id = 1, PersonName = "张三", PersonGender = "男", BirthOfDate = null },
                new Person { Id = 2, PersonName = "李四", PersonGender = "女", BirthOfDate = null },
                new Person { Id = 3, PersonName = "王五", PersonGender = "男", BirthOfDate = null }
            };
            return new JsonResult(list);
        }
    }
}

运行结果如下所示,可以发现BirthOfDate字段并未被序列化。

[
  {
    "id": 1,
    "personName": "张三",
    "personGender": "男"
  },
  {
    "id": 2,
    "personName": "李四",
    "personGender": "女"
  },
  {
    "id": 3,
    "personName": "王五",
    "personGender": "男"
  }
]

3.5.、JSON忽略只读字段

Person中添加一个只读字段Info,代码如下:

using System;

namespace App
{
    public class Person
    {
        public int Id { get; set; }
        public string PersonName { get; set; }
        public string PersonGender { get; set; }
        public DateTime? BirthOfDate { get; set; }
        public string Info
        {
            get { return $"姓名:{PersonName},性别:{PersonGender},出生日期:{BirthOfDate}"; }
        }
    }
}

关于忽略只读字段,System.Text.Json已经支持设置该属性,但Newtonsoft.Json并没有提供对应属性来支持它,因此我们需要自己动手实现。新建一个类IgnoreReadOnlyPropertiesResolver,代码如下:

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;

namespace App
{
    public class IgnoreReadOnlyPropertiesResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
            return props.Where(p => p.Readable && p.Writable).ToList();
        }
    }
}

然后将ContractResolver属性的值替换为IgnoreReadOnlyPropertiesResolver,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;

                // 忽略只读字段
                options.SerializerSettings.ContractResolver = new IgnoreReadOnlyPropertiesResolver();

                // 忽略null值
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

运行结果如下所示,可以发现Info字段并未被序列化。

[
  {
    "Id": 1,
    "PersonName": "张三",
    "PersonGender": "男",
    "BirthOfDate": "2000-01-01T00:00:00"
  },
  {
    "Id": 2,
    "PersonName": "李四",
    "PersonGender": "女",
    "BirthOfDate": "2000-02-02T00:00:00"
  },
  {
    "Id": 3,
    "PersonName": "王五",
    "PersonGender": "男",
    "BirthOfDate": "2000-03-03T00:00:00"
  }
]

3.6、JSON中的时间格式

System.Text.Json中,我们需要通过自定义类来实现时间字段的格式化, 而Newtonsoft.Json中的时间格式化则非常简单,我们只需要对DateFormatString进行设置即可,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;

                // 忽略只读字段
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

                // 忽略null值
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;

                // 设置时间格式
                options.SerializerSettings.DateFormatString = "yyyy年MM月dd日 HH时mm分ss秒";
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

运行结果如下所示,可以发现时间字段已经被格式化。

[
  {
    "id": 1,
    "personName": "张三",
    "personGender": "男",
    "birthOfDate": "2000年01月01日 00时00分00秒"
  },
  {
    "id": 2,
    "personName": "李四",
    "personGender": "女",
    "birthOfDate": "2000年02月02日 00时00分00秒"
  },
  {
    "id": 3,
    "personName": "王五",
    "personGender": "男",
    "birthOfDate": "2000年03月03日 00时00分00秒"
  }
]

3.7、忽略循环引用

如果涉及到一对多关联表的查询时,JSON序列化会产生循环引用问题,解决方法就是对ReferenceLoopHandling进行设置,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace App
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                // 格式化JSON文本
                options.SerializerSettings.Formatting = Formatting.Indented;

                // 忽略只读字段
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

                // 忽略null值
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;

                // 设置时间格式
                options.SerializerSettings.DateFormatString = "yyyy年MM月dd日 HH时mm分ss秒";

                // 忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

4、反序列化操作

Newtonsoft.Json中的反序列化操作很简单,只需要调用JsonConvert.DeserializeObject即可,代码如下:

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace App.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        [HttpGet]
        public ActionResult<string> Get()
        {
            string json = "{\"Id\":1,\"PersonName\":\"张三\",\"PersonGender\":\"男\",\"BirthOfDate\":\"2000-01-01 00:00:00\"}";
            Person person = JsonConvert.DeserializeObject<Person>(json);
            return $"姓名:{person.PersonName}\n性别:{person.PersonGender}\n出生日期:{person.BirthOfDate}";
        }
    }
}

运行结果如下所示:

姓名:张三
性别:男
出生日期:2000/1/1 0:00:00

5、结语

本文主要介绍了Newtonsoft.Json的使用方法。其实System.Text.JsonNewtonsoft.Json的使用方法都很简便,具体在项目中使用哪个序列化工具可根据情况自行决定。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值