序列化有时是数组的Json属性

时间:2015-05-10 03:02:38

标签: c# json.net

有没有办法在单个操作中序列化从十进制到十进制[]的Json对象属性?

在我的Json产品Feed中,特价商品表示为数组(正常价格/促销价)。普通商品只是价格。像这样:

[
    {
        "product" : "umbrella",
        "price" : 10.50,
    },
        "product" : "chainsaw",
        "price" : [
                      39.99,
                      20.0
                    ]
    }
]

我能让它工作的唯一方法是,如果我将属性设为如此对象:

public class Product
{
    public string product { get; set; }
    public object price { get; set; }
}

var productList = JsonConvert.DeserializeObject<List<Product>>(jsonArray);

但是如果我尝试将其设为decimal []那么它将在单个十进制值上抛出异常。使它成为一个对象意味着数组值是一个JArray所以我以后必须做一些清理工作,我的应用程序中的其他映射要求属性类型是准确的所以我必须将其映射到未映射的属性然后初始化另一个属性没什么大不了的,但命名有点混乱。

对象是这里唯一的选择,还是我可以使用序列化程序做一些魔术,要么将单个值添加到数组,要么将第二个值添加到单独的属性中以获得特价?

2 个答案:

答案 0 :(得分:19)

您必须为该java属性编写自定义转换器(因为它的格式不正确),并使用如下:

price

然后正常解析:

 public class Product
    {
        public string product { get; set; }
        [JsonConverter(typeof(MyConverter ))]
        public decimal[] price { get; set; }
    }


 public class MyConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return false;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if(reader.TokenType == JsonToken.StartArray)
            {
                return serializer.Deserialize(reader, objectType);
            }
            return new decimal[] { decimal.Parse(reader.Value.ToString()) };              
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }

答案 1 :(得分:3)

另一种方法是添加一个dynamic的Json字段,并用JsonProperty属性标记它,以便它与实际的Json对齐。然后在.NET中使用真正的字段来获取Json字段并将其转换为真实数组,如此...

using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class Program
{
    public static void Main()
    {
        var json = "{ \"price\": [ 10, 20 ] }";
        var json2 = "{ \"price\": 15 }";

        var foo1 = JsonConvert.DeserializeObject<Foo>(json);
        var foo2 = JsonConvert.DeserializeObject<Foo>(json2);

        foo1.Price.ForEach(Console.WriteLine);
        foo2.Price.ForEach(Console.WriteLine);
    }
}

public class Foo {
    [JsonProperty(PropertyName = "price")]
    public dynamic priceJson { get; set; }

    private List<int> _price;

    public List<int> Price {
        get {
            if (_price == null) _price = new List<int>();

            _price.Clear();

            if (priceJson is Newtonsoft.Json.Linq.JArray) {

                foreach(var price in priceJson) {
                    _price.Add((int)price);
                }
            } else {
                _price.Add((int)priceJson);
            }

            return _price;
        }
    }
}

现场样本:https://dotnetfiddle.net/ayZBlL