C# 使用一个键的多个数据类型反序列化JSON文件
我想分析电报聊天,所以我导出了一个JSON格式的聊天,并想将其反序列化到我的分析软件中C# 使用一个键的多个数据类型反序列化JSON文件,c#,json,json.net,deserialization,telegram,C#,Json,Json.net,Deserialization,Telegram,我想分析电报聊天,所以我导出了一个JSON格式的聊天,并想将其反序列化到我的分析软件中 { "id": 397910, "type": "message", "date": "2018-02-21T10:27:59", "edited": "1970-01-01T01:00:00", "from": "Username", "from_id": 39033284, "text": "Some Text"
{
"id": 397910,
"type": "message",
"date": "2018-02-21T10:27:59",
"edited": "1970-01-01T01:00:00",
"from": "Username",
"from_id": 39033284,
"text": "Some Text"
}
所以我使用了这个简单的代码来读取JSON
List<JSONObject> jsonObjects = JsonConvert.DeserializeObject<List<JSONObject>>(File.ReadAllText(openFileDialog.FileName));
public class JSONObject
{
public int ID;
public string type;
public string date;
public string edited;
public string from;
public int fromID;
public string photo;
public int width;
public int height;
public string text;
}
另外,我发现了这个数据集
{
"id": 397904,
"type": "message",
"date": "2018-02-21T10:18:12",
"edited": "1970-01-01T01:00:00",
"from": "Username",
"from_id": 39033284,
"text": [
{
"type": "link",
"text": "google.com"
},
"\n\nSome Text"
]
}
当数据显示出这种不一致性时,我不知道如何反序列化数据 由于属性很复杂,您需要编写自己的反序列化逻辑 这是我的,但这只是一个例子: 首先,您的文本属性似乎是 单一值 或一个值数组 在本例中,我将使用always list结果,具有单个值的情况将只是具有一个条目的列表
public List<TextProperty> text;
然后,您必须创建自己的转换器来处理此问题,您只需从JsonConverter继承并实现逻辑即可
public class TextPropertyConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException(); // not covered here
}
// A value can be either single string or object
// Return a TextProperty in both cases
private TextProperty ParseValue(JToken value)
{
switch(value.Type)
{
case JTokenType.String:
return new TextProperty { text = value.ToObject<string>() };
case JTokenType.Object:
return value.ToObject<TextProperty>();
default:
return null;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// You'll start either with a single value (we'll convert to list of one value) or an array (list of several values then)
switch(reader.TokenType)
{
case JsonToken.String:
case JsonToken.StartObject:
return new List<TextProperty> { ParseValue(JToken.Load(reader)) };
case JsonToken.StartArray:
var a = JArray.Load(reader);
var l = new List<TextProperty>();
foreach(var v in a)
l.Add(ParseValue(v));
return l;
default:
return null;
}
}
public override bool CanConvert(Type objectType) => false;
}
我认为所有的案例都应该包括在内
要使用它,只需将JsonConverter属性添加到目标属性
public class JSONObject
{
public int id;
public string type;
public string date;
public string edited;
public string from;
public int from_id;
public string photo;
public int width;
public int height;
[JsonConverter(typeof(TextPropertyConverter))]
public List<TextProperty> text;
}
然后测试它:
static void Main(string[] args)
{
string json = @"
[
{
""id"": 397910,
""type"": ""message"",
""date"": ""2018-02-21T10:27:59"",
""edited"": ""1970-01-01T01:00:00"",
""from"": ""Username"",
""from_id"": 39033284,
""text"": ""Some Text""
},
{
""id"": 397911,
""type"": ""message"",
""date"": ""2018-02-21T10:31:47"",
""edited"": ""1970-01-01T01:00:00"",
""from"": ""Username"",
""from_id"": 272964614,
""text"": [
""Some Text "",
{
""type"": ""mention"",
""text"": ""@school""
},
"" Some Text""
]
}
]";
List<JSONObject> jsonObjects = JsonConvert.DeserializeObject<List<JSONObject>>(json);
Console.Read();
}
结果如下:
由于属性很复杂,您需要编写自己的反序列化逻辑 这是我的,但这只是一个例子: 首先,您的文本属性似乎是 单一值 或一个值数组 在本例中,我将使用always list结果,具有单个值的情况将只是具有一个条目的列表
public List<TextProperty> text;
然后,您必须创建自己的转换器来处理此问题,您只需从JsonConverter继承并实现逻辑即可
public class TextPropertyConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException(); // not covered here
}
// A value can be either single string or object
// Return a TextProperty in both cases
private TextProperty ParseValue(JToken value)
{
switch(value.Type)
{
case JTokenType.String:
return new TextProperty { text = value.ToObject<string>() };
case JTokenType.Object:
return value.ToObject<TextProperty>();
default:
return null;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// You'll start either with a single value (we'll convert to list of one value) or an array (list of several values then)
switch(reader.TokenType)
{
case JsonToken.String:
case JsonToken.StartObject:
return new List<TextProperty> { ParseValue(JToken.Load(reader)) };
case JsonToken.StartArray:
var a = JArray.Load(reader);
var l = new List<TextProperty>();
foreach(var v in a)
l.Add(ParseValue(v));
return l;
default:
return null;
}
}
public override bool CanConvert(Type objectType) => false;
}
我认为所有的案例都应该包括在内
要使用它,只需将JsonConverter属性添加到目标属性
public class JSONObject
{
public int id;
public string type;
public string date;
public string edited;
public string from;
public int from_id;
public string photo;
public int width;
public int height;
[JsonConverter(typeof(TextPropertyConverter))]
public List<TextProperty> text;
}
然后测试它:
static void Main(string[] args)
{
string json = @"
[
{
""id"": 397910,
""type"": ""message"",
""date"": ""2018-02-21T10:27:59"",
""edited"": ""1970-01-01T01:00:00"",
""from"": ""Username"",
""from_id"": 39033284,
""text"": ""Some Text""
},
{
""id"": 397911,
""type"": ""message"",
""date"": ""2018-02-21T10:31:47"",
""edited"": ""1970-01-01T01:00:00"",
""from"": ""Username"",
""from_id"": 272964614,
""text"": [
""Some Text "",
{
""type"": ""mention"",
""text"": ""@school""
},
"" Some Text""
]
}
]";
List<JSONObject> jsonObjects = JsonConvert.DeserializeObject<List<JSONObject>>(json);
Console.Read();
}
结果如下:
你有一个奇怪的Json需求,它不仅是一个数组,而且数组也包含不同的对象集,虽然这个问题的答案是非常定制的,但这里有一个通用的解决方案,它可以很好地处理各种类型,你有一个奇怪的Json需求,它不仅仅是一个数组,但是数组也包含不同的对象集,虽然这个问题的答案是非常定制的,但是这里有一个通用的解决方案,它对各种类型都有很好的效果,这是一个很好的答案,并且正是我们喜欢在这里看到的那种详细的、教育性的答案。谢谢是的,非常感谢-它做到了这一点,我不仅可以使用你的解决方案,我也理解它,并可以将其应用于未来的问题:这是一个很好的答案,正是我们喜欢在这里看到的那种详细的、有教育意义的答案。谢谢是的,非常感谢-它做到了这一点,我不仅可以使用你的解决方案,我也理解它,可以将它应用到未来的问题上:D