C# 使用JSON.net处理(反)序列化主数据
在使用JSON.NET时,我遇到了MasterData在GET和POST操作方面的一个问题 以电影为例,在反序列化之前,我可以在get操作中获得以下JSON:C# 使用JSON.net处理(反)序列化主数据,c#,serialization,json.net,deserialization,C#,Serialization,Json.net,Deserialization,在使用JSON.NET时,我遇到了MasterData在GET和POST操作方面的一个问题 以电影为例,在反序列化之前,我可以在get操作中获得以下JSON: { “movie”: { “name”:”bad boys”, ”genre”: { “id”:"1", ”name”:”thriller” } } } { “movie”: { “name”
{
“movie”: {
“name”:”bad boys”,
”genre”: {
“id”:"1",
”name”:”thriller”
}
}
}
{
“movie”: {
“name”:”bad boys”,
”genre”:"1"
}
}
{
"movie": {
"name": "bad boys",
"genre": {
"id": "1"
}
}
}
但是,在POST操作中,我希望构造一个序列化字符串,如下所示:
{
“movie”: {
“name”:”bad boys”,
”genre”: {
“id”:"1",
”name”:”thriller”
}
}
}
{
“movie”: {
“name”:”bad boys”,
”genre”:"1"
}
}
{
"movie": {
"name": "bad boys",
"genre": {
"id": "1"
}
}
}
如您所见,通过GET操作,我需要反序列化完整的对象,而在serializeforpost上,我只需要添加Id,但使用相同的JsonPropertyName
获得这种情况的最干净的方法是什么?我一直在尝试使用IContractResolver和IReferenceResolver,但这两个工具都没有让我达到目的。还尝试使用propertynames,例如:
[JsonProperty(PropertyName=“genre”)]
公共类型{get;set;}
[JsonProperty(PropertyName=“genre”)]
公共字符串GenreId{get{return Genre!=null?Genre.Id:0;}
我也尝试过使用ShouldSerialize[MemberName]和ShouldDeserialize[MemberName]两种情况,但它们给出了一个异常,即我不能使用两个同名属性,这在某种程度上是合乎逻辑的
目前,我唯一剩下的想法是使用DTO进行序列化,但我更喜欢更干净的解决方案。欢迎大家提出建议 用于此。您想检查
类型
属性的类型,并将其读取为对象
或int
在我看来,使用DTO是最干净的解决方案。由于GET/POST的模型不同,因此理想情况下需要两个单独的模型。我滥用了NullValueHandling.Ignore
序列化程序设置,这意味着您可以在这两种情况下使用相同的模型,前提是您不介意总是在类型上使用Id
属性:
class MovieJsonWrapper
{
[JsonProperty("movie")]
public Movie Movie { get; set; }
}
class Movie
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("genre")]
public Genre Genre { get; set; }
}
class Genre
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
然后,我们可以将其用于:
var movie = new Movie
{
Name = "bad boys",
Genre = new Genre
{
Id = "1"
}
};
var movieJsonWrapper = new MovieJsonWrapper { Movie = movie };
var jsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
var json = JsonConvert.SerializeObject(movieJsonWrapper, jsonSerializerSettings);
这将产生以下结果:
{
“movie”: {
“name”:”bad boys”,
”genre”: {
“id”:"1",
”name”:”thriller”
}
}
}
{
“movie”: {
“name”:”bad boys”,
”genre”:"1"
}
}
{
"movie": {
"name": "bad boys",
"genre": {
"id": "1"
}
}
}
类似地,我们可以使用以下命令反序列化GET响应:
var result = JsonConvert.DeserializeObject<MovieJsonWrapper>(raw);
var result=JsonConvert.DeserializeObject(原始);
如果在发布时确实需要放弃该类型的Id
属性,那么您需要额外的模型。此解决方案减少了样板文件的数量。您可以编写自定义转换器
public class GenreConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Genre);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return JObject.Load(reader).ToObject<Genre>();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var genre = value as Genre;
writer.WriteValue(genre.id);
}
}
在@pavel krymets的最初提示之后,我自己刚刚发布了这个答案。我试过了,结果很好。最好的解决方案!另外:因为我只需要为序列化部分定制一个转换器,所以我还使用了公共覆盖bool CanRead{get{return false;}},这会导致读取部分忽略genrecoverter,并使用普通的JsonConverter…感谢您的初始提示,我自己能够解决这个问题。真正的答案投票给EZI,因为已完成的示例供其他人参考,但你在哪里找到了我!谢谢我能感觉到你对有两种不同型号用于不同目的的看法。然而,由于我正在处理一个外部API,所以我无法对需要发送和接收的JSON的结构产生任何影响。因此,在EZI的完整示例中使用自定义转换器最适合我。谢谢你的回答!