【问题标题】:Issues with Serializing PropertyName with Property Type序列化属性名称与属性类型的问题
【发布时间】:2014-02-13 06:17:36
【问题描述】:

我正在使用 Netonsoft.Json 和 ASP.Net Web API。

我必须生成一个json字符串,如下所示,

"view":
[
{"id": "MAIN_TOP_IMAGE_b", 
    "image":
    {
        "value": "Base64 encoding(image.jpg)",
        "type": "jpg;base64",
        "align": "right"
    }
},
{"id": "MAIN_BARCODE_a", 
    "barcode":
    {
        "value": " 32455232453",
        "type": "QRCODE",
        "caption": "1432343fdoadkfe"
    }
}
]

我已经创建了一个如下的类,

public class View
{   
    [JsonProperty("id")]
    public string Id { get; set; }
    public Object ElementData { get; set; }
}

public class Image
{
    [JsonProperty("value")]
    public string Value { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("align")]
    public string Align { get; set; }

    [JsonProperty("bgcolor")]
    public string BGColor { get; set; }
}

public class Text
{
    [JsonProperty("value")]
    public string Value { get; set; }

    [JsonProperty("color")]
    public string Color { get; set; }

    [JsonProperty("align")]
    public string Align { get; set; }
}

public class Barcode
{
    [JsonProperty("value")]
    public string Value { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("caption")]
    public string Caption { get; set; }
}

而 ElementData 将具有对象之一(图像、条形码、文本) elementdata 属性名称应使用其类型。

有什么办法吗?

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    你可以创建一个自定义的 Json 转换器来做任何你想做的事,你想做的任何事情。 就像描述的here

    在 write 方法中只需检查对象的类型,并相应地对其进行序列化。

    【讨论】:

      【解决方案2】:

      您可以通过为您的 View 类创建自定义 JsonConverter 来解决此问题,如下所示:

      class ViewConverter : JsonConverter
      {
          public override bool CanConvert(Type objectType)
          {
              return (objectType == typeof(View));
          }
      
          public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
          {
              View view = (View)value;
              JObject jo = new JObject();
              jo.Add("id", view.Id);
              if (view.ElementData != null)
              {
                  jo.Add(view.ElementData.GetType().Name.ToLower(),
                         JObject.FromObject(view.ElementData));
              }
              jo.WriteTo(writer);
          }
      
          public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
          {
              throw new NotImplementedException();
          }
      }
      

      然后使用 [JsonConverter] 属性装饰您的 View 类,如下所示:

      [JsonConverter(typeof(ViewConverter))]
      public class View
      {
          [JsonProperty("id")]
          public string Id { get; set; }
          public Object ElementData { get; set; }
      }
      

      您的示例缺少一个容器类来保存视图列表,所以我假设它看起来像这样:

      public class RootObject
      {
          [JsonProperty("view")]
          public List<View> Views { get; set; }
      }
      

      有了所有这些部分,您可以序列化 RootObject 以获得所需的 JSON:

      class Program
      {
          static void Main(string[] args)
          {
              RootObject obj = new RootObject();
              obj.Views = new List<View>
              {
                  new View
                  {
                      Id = "MAIN_TOP_IMAGE_b",
                      ElementData = new Image
                      {
                          Value = "Base64 encoding(image.jpg)",
                          Type = "jpg;base64",
                          Align = "right"
                      }
                  },
                  new View
                  {
                      Id = "MAIN_BARCODE_a",
                      ElementData = new Barcode
                      {
                          Value = " 32455232453",
                          Type = "QRCODE",
                          Caption = "1432343fdoadkfe"
                      }
                  }
              };
      
              string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
              Console.WriteLine(json);
          }
      }
      

      输出:

      {
        "view": [
          {
            "id": "MAIN_TOP_IMAGE_b",
            "image": {
              "value": "Base64 encoding(image.jpg)",
              "type": "jpg;base64",
              "align": "right",
              "bgcolor": null
            }
          },
          {
            "id": "MAIN_BARCODE_a",
            "barcode": {
              "value": " 32455232453",
              "type": "QRCODE",
              "caption": "1432343fdoadkfe"
            }
          }
        ]
      }
      

      【讨论】:

      • 谢谢布赖恩。它就像一个魅力。是的,你说得对,我没有指定你提到的那个额外的类。
      • 很高兴您发现它有帮助。
      【解决方案3】:

      可能能够通过继承得到你想要的......

      public abstract class View
      {   
          public string Id { get; set; }
      }
      
      public class ImageView : View
      {
          public Image Image { get; set; }
      }
      
      public class BarcodeView : View
      {
          public Barcode Barcode { get; set; }
      }
      
      public class TextView : View
      {
          public Text Text { get; set; }
      }
      

      根据 this article,您只需要使用正确的类型名称处理配置 Json.net 序列化程序,它应该可以工作...

      // WebApiConfig.cs
      
      var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
      jsonFormatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects;
      
      // use camelCase resolver to do away with the JsonProperty annotations
      jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
      

      您需要一个具有 View 属性的根对象,该属性是视图列表...

      public class RootObject 
      {
          public List<View> View { get; set; }
      }
      

      【讨论】:

      • 不完全。 TypeNameHandling = TypeNameHandling.Objects 导致序列化程序为 JSON 层次结构中的每个对象输出名称为 $type 的附加属性。它不会根据问题的类型更改现有属性的名称。
      猜你喜欢
      • 1970-01-01
      • 2019-11-02
      • 1970-01-01
      • 2011-10-15
      • 2021-02-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 2021-11-30
      相关资源
      最近更新 更多