繁体   English   中英

在Json.Net中作为CSV字符串的字符串列表

[英]List of strings as CSV string in Json.Net

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

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"}

如何获得代码中的注释所反映的内容?

实现一个自定义JsonConverter可以很好地解决此问题,但是当我使用非通用版本JsonConvert.DeserializeObject(serialized)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]属性添加到您要由转换器处理的类的list属性中:

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

当然,此解决方案假定您的字符串中都没有逗号。 如果您的字符串可以包含逗号,则您需要为逗号使用转义机制以确保成功的往返。 那时,我建议您仅坚持默认的序列化,因为JSON已经具有这种机制。

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


如果没有可用的DTO进行反序列化,则必须使用JObject并且您将无法使用上述转换器。 相反,您可以使用辅助方法将反序列化JToken包含CSV字符串的JArray转换为JToken

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"]);

如果您在调试器中查看serilalized的代码,则如下所示:

"{\"Age\":25,\"Name\":\"Jon\",\"Friends\":[\"Jan\",\"Joe\",\"Tim\"]}"

这是因为serilalized是一个字符串,并且该字符串已在其中嵌入了"

当打印到控制台时,它看起来像这样:

{"Age":25,"Name":"Jon","Friends":["Jan","Joe","Tim"]}

这是完全正确的( FriendsString的列表)。

这里唯一的问题是,你初始化Friends和反序列化添加到,造成6项,而不是3。

如果您确实需要将Friends序列化为用逗号分隔的字符串(我不建议这样做),则需要查看JsonConverter

更新:请注意,这不适用于反序列化到JObject (如您现在所指示的那样)。 您需要查找带有逗号的字符串,并将.Split为目标对象(假设所有带逗号的字符串都应该是字符串列表)。 或者像以前一样进行序列化,您将获得一个包含字符串的JArray 这就是为什么我不建议您尝试这样做的原因:数据的非标准表示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM