【发布时间】:2014-07-10 11:56:33
【问题描述】:
我根据此处引用的示例在我的 MVC 中使用 Newtonsoft JSON:Setting the Default JSON Serializer in ASP.NET MVC。
我的数据契约类看起来像:
[DataContract]
public MyContractClass
{
public MyContractClass()
{
this.ThisPropertyFails = new List<ClassDefinedInAnotherAssembly>();
}
[DataMember(EmitDefaultValue = false, Name = "thisPropertyIsFine")]
public string ThisPropertyIsFine { get; set; }
[DataMember(EmitDefaultValue = false, Name = "thisPropertyFails")]
public IList<ClassDefinedInAnotherAssembly> ThisPropertyFails { get; internal set; }
}
我专门用于反序列化的代码如下所示:
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
return null;
}
var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
var bodyText = reader.ReadToEnd();
if (String.IsNullOrEmpty(bodyText))
{
return null;
}
else
{
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new StringEnumConverter());
serializerSettings.Converters.Add(new ExpandoObjectConverter());
DictionaryValueProvider<object> result = new DictionaryValueProvider<object>(JsonConvert.DeserializeObject<ExpandoObject>(bodyText, serializerSettings), CultureInfo.CurrentCulture);
return result;
}
//return String.IsNullOrEmpty(bodyText) ? null : new DictionaryValueProvider<object>(JsonConvert.DeserializeObject<ExpandoObject>(bodyText, new ExpandoObjectConverter(), new StringEnumConverter()), CultureInfo.InvariantCulture);
}
但是,在 MVC 操作中,ModelState.IsValid 为 false,查看错误,我看到:
{"参数从类型转换 'System.Collections.Generic.List`1[[System.Object, mscorlib, 版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089]]' 键入“OtherAssembly.ClassDefinedInAnotherAssembly”失败,因为 没有类型转换器可以在这些类型之间进行转换。"}
有人知道这里发生了什么吗?同样的类适用于我的 WebApi 项目(在本例中为“OtherAssembly”)。
编辑#1
直接使用已知类型的代码确实有效。所以这与 ExpandoObject 下的属性有关。例如这段代码:
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new StringEnumConverter());
serializerSettings.Converters.Add(new ExpandoObjectConverter());
JsonSerializer serializer = JsonSerializer.Create(serializerSettings);
using (StreamReader streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream))
{
using (JsonReader jsonReader = new JsonTextReader(streamReader))
{
var resultAbc = serializer.Deserialize(jsonReader, typeof(MyContractClass));
}
}
工作得很好。
编辑#2
看来我不是唯一遇到此问题的人。任何使用 MVC 并使用经常引用的源代码来使用 Newtonsoft 的人都无法反序列化复杂的子属性: http://tech.pro/q/34/using-jsonnet-to-deserialize-incoming-json-in-aspnet-mvc
不知道为什么该代码在合约中的 1 级之后甚至都不起作用的情况下如此受欢迎?
【问题讨论】:
-
也许你应该扩展你自己的
JsonConverter来明确转换你的 OtherAssembly.ClassDefinedInAnotherAssembly ? -
@Ksven 我可能可以做到这一点,但有数百甚至数千个课程,所以必须为所有课程都这样做似乎很愚蠢?这没有任何意义。
-
您有 数千个 类要序列化?
-
@Bob。哈哈,我猜几千有点夸张,但我现在确实有 300 多个,而且还在增长(企业应用)。为所有这些都编写特定的转换器是不切实际的,我什至不应该这样做,因为这些完全相同的东西在 WebApi 和 Newtonsoft 中都可以正常工作。
-
希望您只是序列化相关数据而不是整个类,因为数据在这些类中......我一直在使用
MyObjectType myObj = JsonConvert.DeserializeObject<MyObjectType>(temp);直接反序列化对象
标签: c# asp.net asp.net-mvc json json.net