【问题标题】:JSON deserialization to object, with partial dynamic propertiesJSON 反序列化为对象,具有部分动态属性
【发布时间】:2015-12-08 08:40:47
【问题描述】:

我正在调用一个休息服务,该服务返回 JSON 内容。大多数内容都有预定义的结构,但有些内容是动态的,基于传递给其余服务的参数。 一旦我从其余服务获得响应,我想反序列化为一个对象,以便我可以轻松地使用数据。我目前正在使用 DataContractJsonSerializer 来执行此操作。

/// <summary>
/// Deserialize JSON formatted string to an object of a specified type
/// </summary>
/// <typeparam name="T">Object type to deserialize</typeparam>
/// <param name="sJSON">JSON formatted string to deserialize</param>
/// <returns>Returns an instance of an object</returns>
public static T FromJSON<T>(this string sJSON) where T : new()
{
    T oValue;

    using (System.IO.MemoryStream strJSON = new System.IO.MemoryStream())
    {
        using (System.IO.StreamWriter swJSON = new System.IO.StreamWriter(strJSON))
        {
            swJSON.Write(sJSON);
            swJSON.Flush();

            strJSON.Seek(0, System.IO.SeekOrigin.Begin);

            System.Runtime.Serialization.Json.DataContractJsonSerializer ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
            oValue = (T)ser.ReadObject(strJSON);

            return oValue;
        }
    }
}

这是一个休息服务响应的例子:

{
    "entities" : [{
            "type" : "mytest",
            "properties" : {
                "Active" : true,
                "Category" : "10732",
                "Description" : "test test test",
                "LastUpdateTime" : 1446676525195,
                "Id" : "12655"
            }
        }
    ],
    "metadata" : {
        "status" : "OK",
        "count" : 0
    }
}

对象总是有一个“entities”和“metadata”属性,元数据总是有一个“status”和“count”属性,实体总是一个数组,数组中的每一项都有“类型”和“属性”属性。动态特性对属性对象起作用,它将包含完全基于传递给其余服务的属性。

这是类定义,我一直在使用将 json 字符串反序列化为对象。但我不确定如何使属性部分动态化。即使我最终可以得到可行的名称值字典。这可能吗,理想情况下不需要 3rd 方 json 库?

[DataContract]
public class Response
{
    [DataMember(
    public Entity[] entities { get; set; }

    [DataMember(
    public MetaData metadata { get; set; }
}

[DataContract]
public class Entity
{
    [DataMember(
    public string type { get; set; }  

    [DataMember()]
    public Properties properties { get; set; }
}


[DataContract]
public class Properties
{
     //How do I make this part dynamic?
}

[DataContract]
public class MetaData
{
    [DataContract]
    public enum Status
    {
        [EnumMember]
        OK,

        [EnumMember]
        FAILED
    }

    public Status CompletionStatus { get; set; }

    [DataMember()]
    public string status
    {
        get
        {
            return this.CompletionStatus.ToString();
        }
        set
        {
            this.CompletionStatus = (Status)Enum.Parse(typeof(Status), value);
        }
    }

    [DataMember()]
    public int count{ get; set; }
}

【问题讨论】:

  • 将属性设为Dictionary&lt;string, object&gt;
  • @Rob - 这似乎不起作用。 “属性”属性的计数始终为 0。
  • 仔细查看 - 您还需要配置序列化程序以正确序列化 JSON 对象/字典 - 请参阅发布的答案

标签: c# json


【解决方案1】:

将您的属性更改为:

[DataMember]
public Dictionary<string, object> properties { get; set; }

然后你需要配置序列化器:

var ser = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings {
    UseSimpleDictionaryFormat = true 
});

【讨论】:

  • 或者,如果您使用 JSON.net 进行序列化,它会自动处理它
  • 哦,太好了!比我采用的方法要好得多,即创建一个实现 ISerializable 的类,然后使用 Constructor(SerializationInfo info, StreamingContext context);
  • 这是正确的答案,因为大多数对象具有固定的结构,只有属性是动态的。其他答案使整个对象动态化。
【解决方案2】:

所以我把你的部分代码放到了一个控制台应用程序中并玩了一下,你想要使用的就是动态类型。

这是我的代码:

static void Main(string[] args)
{
        string test = @" [{
        ""type"" : ""mytest"",
        ""properties"" : {
            ""Active"" : true,
            ""Category"" : ""10732"",
            ""Description"" : ""test test test"",
            ""LastUpdateTime"" : 1446676525195,
            ""Id"" : ""12655""
        }
    },
{
        ""type"" : ""mytest1"",
        ""properties"" : {
            ""Active"" : true,
            ""Category"" : ""10731232"",
            ""Description"" : ""test test1 test"",
            ""LastUpdateTime"" : 144195,
            ""Id"" : ""126155""
        }
    }
]";
        List<Entity> entities = JsonConvert.DeserializeObject<List<Entity>>(test);
        foreach (Entity e in entities)
        {
            Console.WriteLine(e.properties.Active);
        }
        Console.ReadKey();
}

这是我的课:

public class Entity
    {
         public string type { get; set; }
        public dynamic properties { get; set; }
    }

因此,由于属性是动态的,它会从您的 JSon 获取数据并决定其结构需要的外观。我使用 Newtsoft 进行反序列化,但概念应该保持不变。 还要小心,因为它是动态的,某些类型(如 boolean)可能无法正确传输,因此请确保在 C# 中获取它以匹配正确的类型

【讨论】:

    猜你喜欢
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多