我们使用C#System.Runtime.Serialization.Json.DataContractJsonSerializer反序列化JSON。它适用于普通对象,但不适用于List。
例如,如果json字符串在下面,那么它可以正常工作:
{"CacheInsertDateTime":"\/Date(1360761324878)\/","Data":{"__type":"SomeObject:#ConsoleApplication1","Symbol":"some string"}}
但如果josn低于:
{"CacheInsertDateTime":"\/Date(1360761324878)\/","Data":[{"__type":"SomeObject:#ConsoleApplication1","Symbol":"some string"},{"__type":"SomeObject:#ConsoleApplication1","Symbol":"some other string"}]}
数据来自List<Object>
而非List<SomeObject>
。我也附上了样品溶液,显示出同样的问题。任何帮助或指示都表示赞赏。
编辑:添加了代码
{
命名空间ConsoleApplication1 { 课程 { / * Someobject类* / [DataContract] 公共类SomeObject { public SomeObject(string sym) { this.Symbol = sym; } [数据成员] public string Symbol {get;组; }
}
/* Cahe Data */
[DataContract()]
[KnownType("GetKnownTypes")]
class CacheData
{
[DataMember()]
public object Data { get; set; }
[DataMember()]
public DateTime CacheInsertDateTime { get; set; }
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
return GetKnownTypes();
}
public static IEnumerable<Type> GetKnownTypes()
{
if (knownTypes == null)
{
// Since reflection is costly, we will do the lookup once for the known types and persist the data in knownTypes variable
knownTypes = new List<Type>();
// first add types from DataModel assembly get types which are marked with DataContract attribute
var typesInCurrentAssembly = Assembly.GetExecutingAssembly().GetTypes().Where
(t => t.GetCustomAttributes(false).Any(attrib => attrib is DataContractAttribute));
foreach (var type in typesInCurrentAssembly)
{
// add type and list<type> also to the known types list
knownTypes.Add(type);
knownTypes.Add(typeof(List<>).MakeGenericType(type));
}
knownTypes.Add(typeof(DataTable));
}
return knownTypes;
}
private static List<Type> knownTypes = null;
}
/*Cache Response Class*/
class CacheResponse<T> where T : class
{
public CacheData CacheData { get; set; }
public T Data
{
get{return (CacheData != null && CacheData.Data.GetType() == typeof(T)) ? CacheData.Data as T: null;}
}
}
/* Main class */
static void Main(string[] args)
{
//1. first with someobject, it works same as above
string jsonString = "{\"CacheInsertDateTime\":\"\\/Date(1360761324878)\\/\",\"Data\":{\"__type\":\"SomeObject:#ConsoleApplication1\",\"Symbol\":\"some object 1\"}}";
CacheData obj = null;
byte[] byteData = Encoding.UTF8.GetBytes(jsonString);
using (MemoryStream stream = new MemoryStream(byteData))
{
var serializer = new DataContractJsonSerializer(typeof(CacheData));
obj = serializer.ReadObject(stream) as CacheData;
}
CacheResponse<SomeObject> response1 = new CacheResponse<SomeObject>();
response1.CacheData = obj;
SomeObject responseObj = response1.Data; //this response object is fine
//2. with list<someobject>, it does not work
jsonString = "{\"CacheInsertDateTime\":\"\\/Date(1360761324878)\\/\",\"Data\":[{\"__type\":\"SomeObject:#ConsoleApplication1\",\"Symbol\":\"some object 1\"},{\"__type\":\"SomeObject:#ConsoleApplication1\",\"Symbol\":\"some object 2\"}]}";
byteData = Encoding.UTF8.GetBytes(jsonString);
using (MemoryStream stream = new MemoryStream(byteData))
{
var serializer = new DataContractJsonSerializer(typeof(CacheData));
obj = serializer.ReadObject(stream) as CacheData;
}
CacheResponse<List<SomeObject>> response2 = new CacheResponse<List<SomeObject>>();
response2.CacheData = obj;
List<SomeObject> responseList = response2.Data;//this is null
}
}
}
答案 0 :(得分:0)
确保让序列化程序知道列表中的预期类型,例如将其传递给DataContractJsonSerializer
的构造函数。
以下示例按预期工作:
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
public class SomeObject
{
public string Symbol { get; set; }
}
public class MyClass
{
public DateTime CacheInsertTime { get; set; }
public List<object> Data { get; set; }
}
public class Program
{
private const string JsonString = @"{""CacheInsertDateTime"":""\/Date(1360761324878)\/"",""Data"":[{""__type"":""SomeObject:#ConsoleApplication1"",""Symbol"":""some string""},{""__type"":""SomeObject:#ConsoleApplication1"",""Symbol"":""some other string""}]}";
private static void Main()
{
var ser = new DataContractJsonSerializer(typeof (MyClass), new[] {typeof (SomeObject)});
var ms = new MemoryStream(Encoding.ASCII.GetBytes(JsonString));
var obj = (MyClass) ser.ReadObject(ms);
Trace.Assert(obj.Data.Count == 2);
Trace.Assert(((SomeObject) obj.Data[1]).Symbol == "some other string");
}
}
}
注意我是如何将typeof(SomeType)传递给序列化器的构造函数。