如何在反序列化JSON字符串时执行String.Join?

时间:2013-08-16 16:46:55

标签: c# json json.net

我的JSON字符串

{
    "account_id": "123456",
    "capabilities": [
        2,
        6,
        15,
        11
    ],
   "currency": "USD"
}

我的班级定义

public class AdAccount
{
    public long account_id { get; set; }
    public string currency { get; set; }
    public List<int> capabilities { get; set; }
}

去骨化代码:

var account = JsonConvert.DeserializeObject<Account>(data, new JsonSerializerSettings() { MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore });

一切正常。但我想要的是“功能”应该是逗号分隔的字符串,如“2,6,15,11”。所以我试过

public class AdAccount
{
    public long account_id { get; set; }
    public string currency { get; set; }
    private string _capabilities;
    public string capabilities { get { return _capabilities; } set { _capabilities = String.Join(",", value); } }
}

但这引发了异常

  

读取字符串时出错。意外的令牌:StartArray。路径   '能力',第1行,第544位。

在反序列化过程中可以做我想做的事吗?

感谢。

4 个答案:

答案 0 :(得分:2)

我建议你制作一个额外的属性来保存显示值(你的CSV)。此属性是只读的,并在列表更新时自动更新/重新计算。

public class AdAccount
{
    public long account_id { get; set; }
    public string currency { get; set; }
    public List<int> capabilities { get; set; }

    public string capabilitiesDisplay
    {
        get
        {
            return string.Join(", ", capabilities);
        }
    }
}

我不确定您是否需要为Json解析器添加忽略以忽略该属性。

这种方法的好处是只有在您访问该值时才会计算该值。

答案 1 :(得分:2)

您可以创建自定义 Converter ,它可以执行从List<int>到字符串的隐式转换

var obj = JsonConvert.DeserializeObject<AdAccount>(json,new MyConverter());

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (objectType == typeof(string) && reader.TokenType == JsonToken.StartArray)
        {
            List<long> nums = new List<long>();
            reader.Read();
            while (reader.TokenType != JsonToken.EndArray)
            {
                nums.Add((long)reader.Value);
                reader.Read();
            }
            return String.Join(",", nums);
        }
        return existingValue;
    }

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

public class AdAccount
{
    public long account_id { get; set; }
    public string currency { get; set; }
    public string capabilities { get;set; }
}

答案 2 :(得分:0)

我建议你有两个陈述:

  • 具有List<int>
  • 的“自然”表示
  • 具有已加入string
  • 的“数据库”表示形式

您可以轻松地将转换器从一个转换为另一个转换器,这意味着您无需在序列化/反序列化路径本身中执行任何特殊操作。当然,成本是你最终得到两个模型。我建议让绝大多数代码使用“自然”表示 - 只使用数据库表示作为处理数据库时的垫脚。

答案 3 :(得分:0)

有一个额外的属性,它是List<int>属性的解析版本,并将其设置在List<int>属性的setter中。

public class AdAccount
{
    public long account_id { get; set; }
    public string currency { get; set; }
    private List<int> _capabilities;
    public List<int> capabilities
    {
        get { return _capabilities; }
        set { _capabilities = value; this.ParsedCapabilities = string.Join(",", value); }
    }
    public string ParsedCapabilities { get; set; }
}