使用未知值类型反序列化 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;

    }
}