c# asp.net核心中现有类的JSON自定义序列化和反序列化



我有现有的第三方DLL -有几个类。我没有这个DLL的源代码。让我们假设它有如下定义的Book类

public class Book
{ 
public String Id { get; set; }
public String Title { get; set; }
public String Author{ get; set; }
public List<Page> Pages { get; set; }
}

我创建了Asp.net Core Web API项目,引用了DLL,编写了http GET方法的API控制器。

[HttpGet("{id}")]
public ActionResult<Book> Get(string id)
{
Book b = Book.FindById(id); // This utility function returns Book instance.
return Ok(b);
}

我的要求是JSON的返回值应该类似于

{
"id" : "1234",
"Title" : "How to Custom Serialize JSON",
"Author" : "Myself",
"NumberOfPages" : 100
}

所以基本上,每当JSON序列化发生时,我要确保Pages属性不被序列化,因为它有许多复杂性。但我应该可以添加新属性NumberOfPages。基本上,我想控制序列化。我见过很多例子,但我找不到这个特殊的情况下,我想自定义序列化现有的类。

我现在不担心反序列化。

我可以看到序列化从 开始
Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteObject(TextWriter writer, Object value)

为了有一个全局有效的解决方案:

  1. 创建自定义转换器
  2. 注册该转换器

创建转换器最简单的方法:创建一个从JsonConverter派生的类:

public class BookConverter : JsonConverter<Book>
{
public override void WriteJson(JsonWriter writer, Book value, JsonSerializer serializer)
{
var bookObject = (JObject)JToken.FromObject(value);
bookObject.Remove(nameof(value.Pages));
bookObject.Add(new JProperty("NumberOfPages", value.Pages.Count));
bookObject.WriteTo(writer);
}
public override Book ReadJson(JsonReader reader, Type objectType, Book existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return new Book(); //TODO: fix me, now it is enough to make it compile
}
}
  • 这里我已经将Book实例(value)转换为JObject
  • 我通过调用Remove来忽略Pages属性。
  • 我通过调用Add来扩展NumberOfPages输出。
  • 我跳过了ReadJson部分,因为它超出了这个问题的范围。

注册转换器

。. NET Core 2.x

public void ConfigureServices(IServiceCollection services)
{
services
.AddControllers()
.AddJsonOptions(opts =>
{
opts.SerializerSettings.Converters.Add(new BookConverter());
});
}

。. NET Core 3。.NET 5.x

在ASP。. NET Core 3.1或更高版本的默认json序列化器是System.Text.Json。为了使用Json。Net需要安装Microsoft.AspNetCore.Mvc.NewtonsoftJson包。这公开了一个名为AddNewtonsoftJson的方法,您可以在其中注册自定义转换器:

public void ConfigureServices(IServiceCollection services)
{
services
.AddControllers()
.AddNewtonsoftJson(opts =>
{
opts.SerializerSettings.Converters.Add(new BookConverter());
});
}

使用这种方法,所有的Book实例将被转换成所需的格式。. NET Core调用序列化器

我会采取不同的方法:

  • 为公共API创建简单的数据传输对象(dto)。这样你就可以添加你想要的属性,而不需要隐藏。
  • 使用Automapper在第三方类和DTO对象之间执行繁琐的属性复制。

要更好地描述这个想法,请参阅例如https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5

最新更新