使用未知值类型反序列化 JSON
Deserialize JSON with a unknown value type
使用 C#,特别是 JSON.net 如何处理可以具有动态值的 JSON 对象。例如:
{
"message_id":"123-456",
"data":["data","list"],
"type":"MSG_TYPE1"
}
{
"message_id":"123-457",
"data":"my data string",
"type":"MSG_TYPE2"
}
{
"message_id":"123-458",
"data":{"key1":"value1","key2":"value2"},
"type":"MSG_TYPE3"
}
"data" 值可以是任何类型。在 C# 中,我定义了一个包含这些属性的 ServiceMessage class,但是 "data" 应该是什么类型的 属性。我正在查看 JToken 或 JContainer,但我不确定实现的最佳方式。
public class ServiceMessage
{
public string message_id { get; set; }
public JContainer data { get; set; }
public string type { get; set; }
public string getJSON()
{
string json = JsonConvert.SerializeObject(this);
return json;
}
public void setJSON(string json)
{
dynamic jsonObj = JsonConvert.DeserializeObject(json);
this.message_id = jsonObj.message_id;
this.type = jsonObj.type;
this.data = // what goes here.
}
}
你用这些数据做什么?将其保留为 json 字符串并在需要数据时处理它可能是有意义的。
好吧,我不确定这是否正确,但这是我想出的。
我大量借用了 here
class ServiceMessageConverter : CustomCreationConverter<ServiceMessage>
{
public override ServiceMessage Create(Type objectType)
{
return new ServiceMessage();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var msg = new ServiceMessage();
string data_string = "";
//get an array of the object's props so I can check if the JSON prop s/b mapped to it
var objProps = objectType.GetProperties().Select(p => p.Name.ToLower()).ToArray();
while (reader.Read())
{
if (reader.Value == null)
{
continue;
}
// read the property name
string readerValue = reader.Value.ToString().ToLower();
// read the property value
if (reader.Read())
{
// make sure the complex types are saved as strings
if (readerValue.ToLower() == "data")
{
if (reader.TokenType == JsonToken.StartObject)
{
dynamic data_obj = serializer.Deserialize(reader);
data_string = data_obj.ToString();
}
else if (reader.TokenType == JsonToken.StartArray)
{
dynamic data_obj = serializer.Deserialize(reader);
data_string = data_obj.ToString();
}
else
{
data_string = reader.Value.ToString();
}
// stuff the data element value into the ServiceMessage
PropertyInfo pi = msg.GetType().
GetProperty("data", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
pi.SetValue(msg, data_string);
}
else
{
// stuff the value into the ServiceMessage
PropertyInfo pi = msg.GetType().
GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType);
pi.SetValue(msg, convertedValue, null);
}
}
}
return msg;
}
}
使用 C#,特别是 JSON.net 如何处理可以具有动态值的 JSON 对象。例如:
{ "message_id":"123-456", "data":["data","list"], "type":"MSG_TYPE1" }
{ "message_id":"123-457", "data":"my data string", "type":"MSG_TYPE2" }
{ "message_id":"123-458", "data":{"key1":"value1","key2":"value2"}, "type":"MSG_TYPE3" }
"data" 值可以是任何类型。在 C# 中,我定义了一个包含这些属性的 ServiceMessage class,但是 "data" 应该是什么类型的 属性。我正在查看 JToken 或 JContainer,但我不确定实现的最佳方式。
public class ServiceMessage
{
public string message_id { get; set; }
public JContainer data { get; set; }
public string type { get; set; }
public string getJSON()
{
string json = JsonConvert.SerializeObject(this);
return json;
}
public void setJSON(string json)
{
dynamic jsonObj = JsonConvert.DeserializeObject(json);
this.message_id = jsonObj.message_id;
this.type = jsonObj.type;
this.data = // what goes here.
}
}
你用这些数据做什么?将其保留为 json 字符串并在需要数据时处理它可能是有意义的。
好吧,我不确定这是否正确,但这是我想出的。 我大量借用了 here
class ServiceMessageConverter : CustomCreationConverter<ServiceMessage>
{
public override ServiceMessage Create(Type objectType)
{
return new ServiceMessage();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var msg = new ServiceMessage();
string data_string = "";
//get an array of the object's props so I can check if the JSON prop s/b mapped to it
var objProps = objectType.GetProperties().Select(p => p.Name.ToLower()).ToArray();
while (reader.Read())
{
if (reader.Value == null)
{
continue;
}
// read the property name
string readerValue = reader.Value.ToString().ToLower();
// read the property value
if (reader.Read())
{
// make sure the complex types are saved as strings
if (readerValue.ToLower() == "data")
{
if (reader.TokenType == JsonToken.StartObject)
{
dynamic data_obj = serializer.Deserialize(reader);
data_string = data_obj.ToString();
}
else if (reader.TokenType == JsonToken.StartArray)
{
dynamic data_obj = serializer.Deserialize(reader);
data_string = data_obj.ToString();
}
else
{
data_string = reader.Value.ToString();
}
// stuff the data element value into the ServiceMessage
PropertyInfo pi = msg.GetType().
GetProperty("data", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
pi.SetValue(msg, data_string);
}
else
{
// stuff the value into the ServiceMessage
PropertyInfo pi = msg.GetType().
GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType);
pi.SetValue(msg, convertedValue, null);
}
}
}
return msg;
}
}