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

本文关键字:执行 String Join 字符串 JSON 反序列化 | 更新日期: 2023-09-27 18:27:55

我的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 });

这一切都很好。然而,我想要的是"capabilities"应该是一个逗号分隔的字符串,如"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。

在反序列化过程中可以执行我想要的操作吗?

谢谢。

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

我建议您制作一个额外的属性来保存显示值(您的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解析器添加一个ignore来忽略该属性。

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

您可以创建一个自定义的转换器,它可以执行从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; }
}

我建议您有两种表示:

  • 具有List<int>的"自然"表示
  • 具有联接的string的"数据库"表示

您可以轻松地将转换器从一个写入到另一个,这意味着您不需要在序列化/反序列化路径本身中做任何特殊的事情。当然,代价是你最终会得到两个型号。我建议让你的绝大多数代码使用"自然"表示——只使用DB表示作为处理数据库的垫脚石。

拥有一个额外的属性,该属性是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; }
}