我的json字符串包括固定类型标题和非固定类型主体如下:
[DataContract]
public class ServiceResponseHeader
{
[DataMember]
public string ErrorCode { get; set; }
[DataMember]
public string Message { get; set; }
}
[DataContract]
public class ServiceResponse
{
[DataMember]
public ServiceResponseHeader Header { get; set; }
[DataMember]
public object Body { get; set; }
}
在运行时,我可以从配置文件中获取Body的类型,但是如何通过DataContractJsonSerializer.ReadObject()将json消毒到指定的对象类型?
示例代码:
string json = @"{ "Header": {"ErrorCode":"0000", "Message":"Got Profile Successfully"}, "Body": [{"DisplayName":"Mike Code","PictureUrl":null,"Title":"Manager"}] }"
Type objType = Type.GetType("MyAssembly.MyTypeName"); //Get Type from configuration file
ServiceResponse obj = new ServiceResponse ()
{
Header = new ServiceResponseHeader(),
Body = Activator.CreateInstance(objType)
};
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
ServiceResponse returnObj = (ServiceResponse)serializer.ReadObject(ms);
}
这里我可以正确获取Header(returnObj.Header.Message),但是returnObj.Body不是MyAssembly.MyTypeName的类型,我无法获取它的属性。
有任何解决此类问题的建议吗?
答案 0 :(得分:0)
通过使用接口而不是对象,并使用DataContractJsonSerializer(http://msdn.microsoft.com/en-us/library/bb908209.aspx)的“指定已知类型”版本来解决此问题是否可行?
看起来像
var serializer = new DataContractJsonSerializer(typeof(IMySerializable), new [] {
typeof(ConcreteSerializable1),
typeof(ConcreteSerializable2)
});
基本上,DataContractSerializer需要您可能序列化/反序列化的上下文,它不能从JSON的内容推断类型。如果您不想这样做,您可能需要考虑第三方库,它将为您提供更多自由来解释JSON。或者JavaScriptSerializer,但与某些第三方库相比,它很慢。
答案 1 :(得分:0)
我一直使用JSON.NET库并且没有使用DataContractJsonSerializer
的经验,所以我将回答JSON.NET。希望您能够翻译为DataContractJsonSerializer
。
如果你定义这样的类:
public class MessageHeader
{
public string TypeName { get; set; }
}
public class Message
{
public MessageHeader Header { get; set; }
public JToken Body { get; set; }
}
您可以像这样使用它们:
var message = JToken.Parse("...").ToObject<Message>();
if (message.Header.TypeName == "User")
{
var user = message.Body.ToObject<User>();
}
else if (message.Header.TypeName == "Answer")
{
var answer = message.Body.ToObject<Answer>();
}
User
和Answer
类可能如下所示:
public class User
{
public string Name { get; set; }
public string Email { get; set; }
}
public class Answer
{
public bool IsSolution { get; set;}
public string Content { get; set; }
}
这将让您处理此消息:
{
"Header": { "TypeName": "User" },
"Body": { "Name": "John Smith", "Email": "jsmith@live.com" }
}
和此消息:
{
"Header": { "TypeName": "Answer" },
"Body" : { "IsSolution": true, "Content": "abc" }
}
答案 2 :(得分:0)
仍然无法通过DataContractJsonSerializer找到任何解决方案,我必须使用JSON.NET来解决这个问题,示例代码如下:
public static dynamic[] Deserialize(Type headerType, Type bodyType, string json)
{
var root = Newtonsoft.Json.Linq.JObject.Parse(json);
var serializer = new Newtonsoft.Json.JsonSerializer();
dynamic header = serializer.Deserialize(root["Header"].CreateReader(),headerType);
dynamic body = serializer.Deserialize(root["Body"].CreateReader(), bodyType);
return new dynamic[] { header, body };
}
headerType是已知的,bodyType可以从配置文件中加载(Type bodyType = Type.GetType(configClassName)),这个公共方法将返回Header和Body对象,然后我可以将它们转换为给定类型的对象我想要。