[英]Parse JSON string using JSON.NET and create a list of strings from a specific array member
[英]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"]}
这是完全正确的( Friends
是String
的列表)。
这里唯一的问题是,你初始化Friends
和反序列化添加到,造成6项,而不是3。
如果您确实需要将Friends
序列化为用逗号分隔的字符串(我不建议这样做),则需要查看JsonConverter 。
更新:请注意,这不适用于反序列化到JObject
(如您现在所指示的那样)。 您需要查找带有逗号的字符串,并将.Split
为目标对象(假设所有带逗号的字符串都应该是字符串列表)。 或者像以前一样进行序列化,您将获得一个包含字符串的JArray
。 这就是为什么我不建议您尝试这样做的原因:数据的非标准表示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.