【问题标题】:Deserialize JSON with a unknown value type使用未知值类型反序列化 JSON
【发布时间】:2015-03-23 02:26:57
【问题描述】:

使用 C# 尤其是 JSON.net 如何处理可以具有动态值的 JSON 对象。例如:

{ "message_id":"123-456", “数据”:[“数据”,“列表”], “类型”:“MSG_TYPE1” }

{ "message_id":"123-457", "data":"我的数据字符串", “类型”:“MSG_TYPE2” }

{ "message_id":"123-458", "数据":{"key1":"value1","key2":"value2"}, “类型”:“MSG_TYPE3” }

“数据”值可以是任何类型。在 C# 中,我定义了一个包含这些属性的 ServiceMessage 类,但“数据”应该是什么类型的属性。我正在查看 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.
    }
}

【问题讨论】:

  • 您知道它们在编译时数据对象的实际结构还是每条消息都包含不同的值?您希望如何查找数据值?
  • 我会根据消息类型知道数据对象的实际结构。如果我知道消息是 MSG_TYPE1 那么我就会知道对象结构。
  • @Huge 在不知道您计划访问该对象的确切方式的情况下,拥有一个强类型对象有点困难,您可以使用泛型做一些事情,但我很确定它会造成比它更多的麻烦值得。一旦数据通过网络传输,您希望如何访问数据?

标签: c# json json.net


【解决方案1】:

你对这些数据做了什么?将其保留为 json 字符串并在需要数据时处理它可能是有意义的。

【讨论】:

  • 一旦消息 id 和消息类型已知,然后检索数据元素。 JSON 来自 python 生产者(但它可以是任何东西)。我正在考虑将数据保存为 JSON 字符串,然后在需要时进行处理,但我不确定是否有更好的方法?
  • stackoverflow.com/questions/13652983/… 有一些信息 - 但基于您的对象当前的外观。我会将其保留为字符串,因为无论如何您最终都必须反序列化。至少当您按消息类型将其拉出时,我至少假设该结构将遵循固定模式并允许您像最初一样继续。
  • 谢谢。所以作为一个新手,我正在反序列化“数据”,似乎 JSON.Net 检测到 JSON 数组、对象等。那么我如何确保特定字段保持为字符串?
  • 所以做一些调查,看起来我可能需要一个自定义转换器来为我做部分反序列化。
【解决方案2】:

好吧,我不确定这是否正确,但这就是我想出的。 我向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;

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    相关资源
    最近更新 更多