并不是Json.net的新手,而是尝试了以下简单示例,将其序列化然后反序列化,得到以下错误:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Collections;
namespace Timehunter.Base.ServicesTests
{
/// <summary>
/// Summary description for JsonError
/// </summary>
[TestClass]
public class JsonError
{
[TestMethod]
public void TestMethod1()
{
JsonSerializerSettings serializerSettings = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset
};
Act.Activities acts = new Act.Activities();
acts.Add(new Act.Activity() { Id = 1, Name = "test1" });
acts.Add(new Act.Activity() { Id = 2, Name = "test2" });
string json = Newtonsoft.Json.JsonConvert.SerializeObject(acts, serializerSettings);
Timehunter.Base.Act.Activities target = Newtonsoft.Json.JsonConvert.DeserializeObject<Timehunter.Base.Act.Activities>(json, serializerSettings);
Assert.AreEqual("test1", target.List[0].Name, "Name of first activity");
}
}
}
namespace Timehunter.Base
{
[DataContract]
public class Activity
{
private int _id;
private string _name;
[DataMember]
public int Id
{
get { return this._id; }
set { this._id = value; }
}
[DataMember]
public string Name
{
get { return this._name; }
set { this._name = value; }
}
public Activity()
{
this._id = new int();
this._name = string.Empty;
}
}
[DataContract]
public class Activities : IEnumerable<Activity>
{
private List<Activity> _list;
[DataMember]
public List<Activity> List
{
get { return this._list; }
set { this._list = value; }
}
public Activities()
{
this._list = new List<Activity>();
}
public void Add(Activity item)
{ this._list.Add(item); }
public bool Remove(Activity item)
{ return this._list.Remove(item); }
public int Count()
{ return this._list.Count; }
public IEnumerator<Activity> GetEnumerator()
{
return this._list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
然后我得到以下错误:
Test Name: TestMethod1
Test FullName: Timehunter.Base.ServicesTests.JsonError.TestMethod1
Test Source: C:\Users\hawi.HAWCONS\Documents\Visual Studio 2015\Projects\Timehunter.Data\Timehunter.Base.ServicesTests\JsonError.cs : line 67
Test Outcome: Failed
Test Duration: 0:00:00,2038359
Result StackTrace:
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewList(JsonReader reader, JsonArrayContract contract, Boolean& createdFromNonDefaultCreator)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Timehunter.Base.ServicesTests.JsonError.TestMethod1() in C:\Users\hawi.HAWCONS\Documents\Visual Studio 2015\Projects\Timehunter.Data\Timehunter.Base.ServicesTests\JsonError.cs:line 79
Result Message:
Test method Timehunter.Base.ServicesTests.JsonError.TestMethod1 threw exception:
Newtonsoft.Json.JsonSerializationException: Cannot create and populate list type Timehunter.Base.Act.Activities. Path '', line 1, position 1.
我究竟做错了什么?
更新2
为了向后兼容,在11.0.2中将其还原。请参阅原始答案以获取解决方案。
更新资料
报告为
问题#1598:DataContractAttribute不会导致IEnumerable的JSon对象序列化,
并已在commit中修复e9e2d00
。它应该在10.0.3之后的下一发行版中,它可能是Json.NET版本11。
原始答案
我注意到您Activities
用[DataContract]
和标记了您的班级[DataMember]
:
[DataContract]
public class Activities : IEnumerable<Activity>
{
private List<Activity> _list;
[DataMember]
public List<Activity> List
{
get { return this._list; }
set { this._list = value; }
}
// ...
}
应用[DataContact]
将导致DataContractJsonSerializer
将一个序列化为IEnumerable<T>
带有属性的JSON对象,而不是JSON数组。由于Json.NET
在应用于非枚举时支持数据协定属性,因此您可能会认为它也会在枚举和集合中尊重它们。
但是,看来这没有实现。如果我使用序列化您的课程DataContractJsonSerializer
,我会看到
{"List":[{"Id":1,"Name":"test1"},{"Id":2,"Name":"test2"}]}
但是,如果我使用Json.NET进行序列化,则会发现[DataContract]
忽略了:
[{"Id":1,"Name":"test1"},{"Id":2,"Name":"test2"}]
然后,稍后它将在反序列化期间引发异常,因为它不知道如何向IEnumerable<Activity>
类中添加成员。(如果您的类已实现ICollection<Activity>
,或者具有带IEnumerable<Activity>
参数的构造函数,则可以添加成员。)
那么,这应该工作吗?文档页面“
序列化属性”指出:
DataContractAttribute可以替代JsonObjectAttribute。DataContractAttribute将默认成员序列化以选择加入。
这意味着Json.NET应该按照您期望的方式工作。如果需要,可以报告有关此问题的信息-
至少应弄清楚文档。
解决方法是
,如果要强制Json.NET将集合序列化为对象,则需要使用[JsonObject]
:
[DataContract]
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class Activities : IEnumerable<Activity>
{
private List<Activity> _list;
[DataMember]
[JsonProperty]
public List<Activity> List
{
get { return this._list; }
set { this._list = value; }
}
// Remainder unchanged.
}
如果您[DataContract]
应用了许多可枚举的类,或者无法在模型中添加对Json.NET的依赖关系,则可以创建一个自定义项ContractResolver
,以检查[DataContract]
on枚举类的存在并将它们序列化为对象:
public class DataContractForCollectionsResolver : DefaultContractResolver
{
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static DataContractForCollectionsResolver instance;
static DataContractForCollectionsResolver() { instance = new DataContractForCollectionsResolver(); }
public static DataContractForCollectionsResolver Instance { get { return instance; } }
protected DataContractForCollectionsResolver() : base() { }
protected override JsonContract CreateContract(Type objectType)
{
var t = (Nullable.GetUnderlyingType(objectType) ?? objectType);
if (!t.IsPrimitive
&& t != typeof(string)
&& !t.IsArray
&& typeof(IEnumerable).IsAssignableFrom(t)
&& !t.GetCustomAttributes(typeof(JsonContainerAttribute),true).Any())
{
if (t.GetCustomAttributes(typeof(DataContractAttribute),true).Any())
return base.CreateObjectContract(objectType);
}
return base.CreateContract(objectType);
}
}
然后使用以下设置:
var serializerSettings = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset,
ContractResolver = DataContractForCollectionsResolver.Instance
};
我有以下WCF数据合同: 当我试图通过Web浏览器访问此服务(它托管在IIS上),我得到了这个错误: 系统运行时。序列化。InvalidDataContractException:类型“MyNamespace”。无法序列化“占用者”。考虑使用DATACONTractAttor属性对其进行标记,并标记要使用DATAMEMBAREATE属性序列化的所有成员。如果类型是集合,请考虑用CopyDATAcN
我的Spring Boot API使用camelCase,但我需要通过我的API将一些请求代理到使用snake_case的第三方API。是否可以将Jackson配置为从snake_case反序列化第三方响应,然后将其序列化回camelCase到我的前端? 所需功能的逐步示例: 示例对象: 我调用我的API API调用第三方 第三方返回 我的API将其反序列化为 我的API序列化对象并返回 现在我使
我有一个这样的JSON: 所有类型都可以包含可变时间,或者只能有一种类型只有一次。 在SpringBoot应用程序中,我有三个类,扩展了公共类。 我有两种方法来序列化和反序列化它。 虽然测试序列化是可以的,但是反序列化在默认情况下不起作用。所以我修改了<code>CommonObject</code>如下: 现在,反序列化工作正常,但序列化不行。json值中包含属性< code>type两次。 有
问题内容: 我试图将onscroll事件处理程序添加到特定的dom元素。看下面的代码: 代码非常简单,如您所见,我想处理div#list滚动。当我运行此示例时,它不起作用。所以我尝试直接在render方法上绑定this._handleScroll,它也不起作用。 因此,我打开了chrome inspector,直接使用以下命令添加了onscroll事件: 它正在工作!我不知道为什么会这样。这是Re
问题内容: 为什么colspan属性在React中不起作用?我创建了呈现以下内容的简单组件: 编辑:解决 这是解决方案。React期望属性名称为 colSpan ,而不是colspan。在浪费了荒谬的时间去发现这个小小的邪恶事实之后,想出了这一点。 问题答案: 来自React的DOM差异文档: 所有DOM属性和属性(包括事件处理程序)都应包含驼峰,以与标准JavaScript样式保持一致。 如果您
本文向大家介绍详解PHP序列化反序列化的方法,包括了详解PHP序列化反序列化的方法的使用技巧和注意事项,需要的朋友参考一下 经常看到一些配置文件里面存放的是一些类似带有格式的变量名称和值,其实就是一个序列化的过程,在需要用到这些数据库的时候会进行一个反序列化过程,就是将这个字符串再还原成他原来的数据结构。下面说说php 如何进行数据的序列化和反序列化的。 php 将数据序列化和反序列化其实就用到两