使用带注释的属性名称反序列化JSON,并使用原始属性名称进行序列化(忽略注释)

时间:2014-08-07 13:21:56

标签: c# json serialization deserialization

我从外部服务接收JSON,并且说JSON可以使用与C#命名规则不兼容的字段名称。如

"$" : {//object definition here} 

我无法将我的课程命名为单个“$”。我正在使用System.Runtime.Serialization数据注释来指定一个字段,从中反序列化这个奇怪命名的对象:

 [DataMember(Name = "$")]
 public Item Info { get; set; }

反序列化有效,但现在我想更好地格式化它,以便它不会再次序列化回"$" : {//object definition here}。有没有办法我可以指定一个序列化规则,说明这个字段需要使用属性名Info进行序列化,同时仍然从名为$的成员反序列化?我希望我的服务用户看到的是:

"Info" : {//object definition here} 

1 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是使用自定义IContractResolver,它基本上告诉Json.Net忽略您的属性名称注释。在反序列化时,您让Json.Net正常工作,因此使用注释。在序列化时,将解析器添加到序列化程序设置,这会导致Json.Net使用您的类属性名称而不是带注释的名称。

以下是解析器所需的代码:

class OriginalNameContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        // Get the JsonProperties (with annotated names) from the base class
        IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);

        // For each property, replace the annotated name with the real name
        foreach (JsonProperty prop in list)
        {
            prop.PropertyName = prop.UnderlyingName;
        }

        return list;
    }
}

以下是演示如何运作的演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"{ ""$"" : { ""$moniker"" : ""blob sprocket"" } }";

        Foo foo = JsonConvert.DeserializeObject<Foo>(json);
        Console.WriteLine("name from JSON = " + foo.Info.Name);
        Console.WriteLine();

        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.ContractResolver = new OriginalNameContractResolver();
        settings.Formatting = Formatting.Indented;

        json = JsonConvert.SerializeObject(foo, settings);
        Console.WriteLine(json);
    }
}

class Foo
{
    [JsonProperty("$")]
    public Item Info { get; set; }
}

class Item
{
    [JsonProperty("$moniker")]
    public string Name { get; set; }
}

输出:

name from JSON = blob sprocket

{
  "Info": {
    "Name": "blob sprocket"
  }
}