Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用JSON.net处理(反)序列化主数据_C#_Serialization_Json.net_Deserialization - Fatal编程技术网

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

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”

在使用JSON.NET时,我遇到了MasterData在GET和POST操作方面的一个问题

以电影为例,在反序列化之前,我可以在get操作中获得以下JSON:

{
     “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的完整示例中使用自定义转换器最适合我。谢谢你的回答!