may*_*lle 5 c# linq serialization json json.net
我在单个文件中有一堆长json输出.我需要读取这些文件并将它们反序列化为最初生成json的实体(我可以访问原始实体).每个文件都有通过序列化类型对象生成的json输出IEnumerable<Response<MyEntity>>.
我试图反序列化时遇到异常,但我不明白为什么.这是我尝试反序列化:
List<string> jsonOutputStrings;
// Read json from files and populate jsonOutputStrings list
List<Response<MyEntity>> apiResponses = new List<Response<MyEntity>>();
foreach (string json in jsonOutputStrings)
{
apiResponses.AddRange(JsonConvert.DeserializeObject<List<Response<MyEntity>>>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }).ToList());
}
Run Code Online (Sandbox Code Playgroud)
我也尝试反序列化到IEnumerable而不是列表:
apiResponses.AddRange(JsonConvert.DeserializeObject<IEnumerable<Response<MyEntity>>>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }).ToList());
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
Newtonsoft.Json.dll发生了'Newtonsoft.Json.JsonSerializationException'类型的第一次机会异常
附加信息:无法创建和填充列表类型System.Linq.Enumerable + WhereSelectListIterator`2 [Entities.Requirement,Entities.RequirementEntity].路径'$ values [0] .ReturnedEntity.Summaries.$ values [0] .Requirements.$ values',line 1,position 715.
整个json太长而无法发布(并且还包含一些机密数据)但我确实在json中找到了一个包含此内容的地方:
"Requirements":{"$id":"7","$type":"System.Linq.Enumerable+WhereSelectListIterator`2[[Entities.Requirement, Entities],[Entities.RequirementEntity, API.Entities]], System.Core","$values":[...]}
Run Code Online (Sandbox Code Playgroud)
在我试图反序列化的实体(最初被序列化的那个)中,Requirements是类型的IEnumerable<Entities.RequirementEntity>.
对我来说,序列化是如何MyEntity起作用而反序列化到同一类型却没有意义.我该如何解决这个问题?
你必须通过浏览Response<>和MyEntity看藏品是如何初始化.这告诉我们某些类中的一个集合是使用Wherelinq中的方法创建的.您可以通过执行以下代码重现此错误:
class MyEntity
{
public MyEntity()
{
Data = new List<string>().Where(x => true);
}
public IEnumerable<string> Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
string data = @"[{""Data"":[""a"",""b""]}]";
var j = JsonConvert.DeserializeObject<IEnumerable<MyEntity>>(data);
}
}
Run Code Online (Sandbox Code Playgroud)
另一种可能性是在json中使用元数据.那么你有2个解决方案:
TypeNameHandling为TypeNameHandling.None(正如评论中提到的那样);TypeNameHandling.None当你拥有IEnumerable<BaseType>并且该列表包含子类型时,使用可能会导致exmaple的反序列化错误BaseType.
在这种情况下,你应该选择第二种选择.基本上,您应该替换任何未反序列化的类型,并将其替换为例如List.
示例代码:
class MyEntity
{
public IEnumerable<string> Data { get; set; }
}
class Program
{
static void Main(string[] args)
{
IList<MyEntity> entities = new MyEntity[] {
new MyEntity { Data = new [] { "1", "2" }.Where(x => x != string.Empty) },
new MyEntity { Data = new [] { "A", "B" }.AsQueryable().Where(x => x != string.Empty) },
new MyEntity { Data = new List<string> { "A", "B" } },
};
string data = JsonConvert.SerializeObject(entities, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
data = Regex.Replace(data, "\"\\$type\":\\s+\"System.Linq.Enumerable\\+WhereArrayIterator(.+?), System.Core\",", "\"$type\": \"System.Collections.Generic.List$1, mscorlib\",", RegexOptions.Singleline);
var j = JsonConvert.DeserializeObject<IEnumerable<MyEntity>>(data, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16681 次 |
| 最近记录: |