繁体   English   中英

使用JSON.net处理(反序列化)主数据

[英]Handling Master Data on (De-)Serialization with JSON.net

使用JSON.NET,我陷入了关于GET和POST操作的MasterData问题。

以电影为例,在反序列化之前可以在GET操作上获取的JSON如下:

{
     “movie”: {
         “name”:”bad boys”,
         ”genre”: {
            “id”:"1",
            ”name”:”thriller”
        }
    }
}

但是,在POST操作中,我想构造如下的序列化字符串:

{
     “movie”: {
         “name”:”bad boys”,
         ”genre”:"1"
    }
}

如您所见,通过GET操作,我需要反序列化整个对象,而在进行POST序列化时,我只需要添加ID,但具有相同的JsonPropertyName。

解决这种情况的最干净的方法是什么? 我一直在尝试使用IContractResolver和IReferenceResolver,但是它们都还没有把我带到那里。 也一直尝试使用属性名作为以下示例:

[JsonProperty(PropertyName = "genre")]
public Genre Genre { get; set; }

[JsonProperty(PropertyName = "genre")]
public string GenreId { get { return Genre != null ? Genre.Id : 0; } }

我也尝试过使用ShouldSerialize [MemberName]和ShouldDeserialize [MemberName]情况,但是这些情况例外,说我不能使用两个具有相同名称的属性,这在某种程度上是合乎逻辑的。

现在,我剩下的唯一想法是使用DTO进行序列化,但我宁愿选择比该解决方案更干净的东西。 欢迎提出建议!

您可以编写一个自定义转换器。

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);
    }
}

您现在所需要的只是使用JsonConverter属性

public class Movie
{
    public string Name { get; set; }
    [JsonConverter(typeof(GenreConverter))]
    public Genre Genre { get; set; }
}

为此使用定制转换器 您要检查genre属性的genre并将其作为objectint读取。

我认为,使用DTO 最干净的解决方案。 由于GET / POST的模型不同,因此理想情况下需要两个单独的模型。 我滥用了NullValueHandling.Ignore序列化程序设置,意味着您可以在两种情况下使用相同的模型, NullValueHandling.Ignore是您不介意始终在Genre上拥有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"
    }
  }
}

同样,我们可以使用以下方法反序列化GET响应:

var result = JsonConvert.DeserializeObject<MovieJsonWrapper>(raw);

如果确实需要在发布时放弃流派上的Id属性,那么您将需要其他模型。 该解决方案减少了样板的数量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM