【问题标题】:How to serialize a DataContract's Members when one property can have different types?当一个属性可以具有不同类型时,如何序列化 DataContract 的成员?
【发布时间】:2014-06-18 06:02:39
【问题描述】:

我有以下 json(由 API 提供):

[
    {
        "type": "text",
        "values": [
            {
                "value": "Text that is in textfield"
            }
        ]
    },
    {
        "type": "category",
        "values": [
            {
                "value": {
                    "text": "Category title",
                    "color": "#000000"
                }
            }
        ]
    }
]

当 values.value 是动态的时,如何将这样的对象呈现为强类型(C# 要求你)?

以下是有关我的问题的更多信息: Trying to map two different types to one value

但我想让这个新问题保持精简。


对不起,我仍然无法让它工作!任何如何序列化的例子?

我目前有这个代码要序列化:

[DataContract]
public class MyField
{
    [DataMember]
    public List<MyValue> values { get; set; }
}

[DataContract]
public class MyValue
{
    [DataMember]
    public object value { get; set; } // This will crash because it needs to be both a string and an object with text,color properties??
}

using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(response)))
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<MyField>));
    return (List<MyField>)serializer.ReadObject(stream);
}

但它在 values.value 位上崩溃,因为它无法转换为强类型...因为它在变化。

////编辑////

肯定有人这样做过!!!

【问题讨论】:

    标签: c# json xaml windows-phone-8


    【解决方案1】:

    基本上你会想要将 Value 定义为字典,因为它是动态的。

    至于你如何序列化它,这取决于你使用的序列化器。我个人更喜欢 Newtonsoft 的 JSON.NET。您可以在 SO 上找到大量关于如何将字典序列化为 JSON 的示例。

    这里是使用datacontractjsonserializer的一个:Deserialize JSON to Dictionary with DataContractJsonSerializer

    这里是一个使用 json.net 的例子:How can I deserialize JSON to a simple Dictionary<string,string> in ASP.NET?

    更新

    以下是如何使用 JSON.NET 反序列化数组中的混合类型并仍然保持强类型。关键是 JSONConverter 实现,它基本上是指示序列化器反序列化为字符串或类型(属性)。

    public static void Main()
    {
        using (FileStream stream = File.OpenRead("TextFile1.txt"))
        using (StreamReader reader = new StreamReader(stream))
        {
            JsonSerializer ser = new JsonSerializer();
            List<MyField> result = ser.Deserialize<List<MyField>>(new JsonTextReader(reader));
        }       
    }
    
    
    
    
    
    public class MyField
    {
        public string type { get; set; }        
        public List<MyValue> values { get; set; }
    }
    
    
    public class MyValue
    {
        [JsonConverter(typeof(MyConverter))]
        public object value { get; set; }
    }
    
    public class MyAttributes
    {
        public string text { get; set; }
        public string color { get; set; }
    }
    
    
    public class MyConverter : JsonConverter
    {
    
        public override bool CanConvert(Type objectType)
        {
            throw new NotImplementedException();
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String)
            {
                return serializer.Deserialize<string>(reader);
            }
            else
            {
                return serializer.Deserialize<MyAttributes>(reader);
            }
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    【讨论】:

    • 我无法让它工作,但我确实找到了这个:msdn.microsoft.com/en-us/library/… ISerializable 类型,我假设我可以在这种类型上重新运行反序列化(在工作 atm 但会尝试当我回到家时)
    • 当我执行 Dictionary 时,它仍然显示 System.InvalidCastException: Unable to cast object of 'System.String' to type 'System.Collections.ICollection' 我显然设置了帖子中提到的设置。
    • 你的完美。好多了,我可以重复使用我已经做过的......曼恩你应该得到一个 6 包!干得好 DUDEEEe
    • 太棒了。很高兴我能帮上忙。
    【解决方案2】:

    DataContractJsonSerializer 在这里没用...

    我终于用上了 Json.Net...

    然后只需将您的字符串传递给解析器(确保它不是一个数组,而是一个包含您的数组的对象)...您可以看到我如何用 pubes 为我的响应添加后缀和前缀:

    JObject jObject = JObject.Parse("{\"data\": " + response + "}");
    JToken jData = jObject["data"];
    

    然后你就可以为所欲为:

    string type = (string)jData["type"];
    

    当然这意味着我现在可以对类型进行切换,然后创建所需类型的对象。

    【讨论】:

    • 啊,看来我太慢了。无论如何,如果您想要一种类型安全的方式来做到这一点,请参阅我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多