c# - Json.Net 中作为 CSV 字符串的字符串列表

标签 c# json.net

我想知道是否可以序列化和反序列化任何 List<string>使用 Json.Net 在 C# 中作为逗号分隔值的字符串:

class MyDTO
{
    public int Age { get; set; } = 25;
    public string Name { get; set; } = "Jon";
    public List<string> Friends { get; set; } = new List<string> {"Jan", "Joe", "Tim"};
}

var serilalized = JsonConvert.SerializeObject(new MyDTO());

//serialized = { "name": "Jon", "age": 25, "friends": "Jan,Joe,Tim" }

var deserialized = JsonConvert.DeserializeObject<MyDTO>(serialized);

//deserialized.Name = "Jon", deserialized.Age = 25, deserialized.Friends = List<string> {"Jan", "Joe", "Tim"}

我怎样才能实现代码中注释所反射(reflect)的内容?

实现自定义 JsonConverter是解决此问题的好方法,但是当我使用非通用版本反序列化时 JsonConvert.DeserializeObject(serialized) ,JsonConverter 无效,反序列化值的类型为 JTokenType.String , 而不是 JTokenType.Array那就是我想要的类型。例如:

JObject obj = (JObject)JsonConvert.DeserializeObject(serilalized);

JToken token = obj["friends"];

Console.WriteLine(token.Type == JTokenType.String); //prints true

Console.WriteLine(token.Type == JTokenType.Array); //prints false

我希望上面的代码可以打印 false在第一种情况下和 true在第二。请注意,在反序列化时我没有类型 MyDTO可用。

最佳答案

我不确定你为什么需要这个,但你可以制作一个简单的 JsonConverter 来做你想做的事:

public class ListToCsvConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<string>);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(string.Join(",", (List<string>)value));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return new List<string>(((string)reader.Value).Split(','));
    }
}

然后将 [JsonConverter] 属性添加到您希望由转换器处理的类中的列表属性:

class MyDTO
{
    [JsonConverter(typeof(ListToCsvConverter))]
    public List<string> Friends { get; set; } = new List<string> { "Jan", "Joe", "Tim" };
}

当然,此解决方案假定您的所有字符串中都不包含逗号。如果您的字符串可以包含逗号,那么您将需要一个逗号转义机制以确保成功往返。在这一点上,我建议只坚持使用默认序列化,因为 JSON 已经有了这样的机制。

往返演示:https://dotnetfiddle.net/dVh4Zq


如果您没有可用于反序列化的 DTO,那么您将不得不使用 JObject,并且您将无法使用上述转换器。相反,您可以使用辅助方法在反序列化后将包含 CSV 字符串的 JToken 转换为 JArray:

static JArray ConvertCsvToArray(JToken value)
{
    if (value.Type == JTokenType.String)
    {
        return JArray.FromObject(((string)value).Split(','));
    }
    throw new ArgumentException("The token does not contain a string value.");
}

像这样使用它:

JObject obj = (JObject)JsonConvert.DeserializeObject(serialized);

JArray array = ConvertCsvToArray(obj["friends"]);

关于c# - Json.Net 中作为 CSV 字符串的字符串列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45283080/

相关文章:

.net - 使用 Newtonsoft.Json 解析 json 时出现 RuntimeBinderException

c# - 从 asp.net 中的文本框中获取希伯来语字符

c# - 路径中的非法字符。将 Skip and Take 与 IEnumerable 一起使用时出错

c# - 使用 NewtonSoft Json.NET 从基类型集合序列化派生类型的属性

c# - ASP.Net Core 1.1 解决方案中检测到自引用循环

c# - 列表中不同值的不同 JsonSerializerSettings

c# - MSChart 轴线

c# - EF Core 是否允许唯一列包含多个空值?

c# - 如何更新链接到 MySQL 数据库的图表?

c# - 通过 JSON.NET 反序列化 Elasticsearch 结果