Newtonsoft.JSON无法使用TypeConverter属性转换模型

我有一个 应用程序,该应用程序将数据作为JSON字符串存储在XML文档以及MySQL DB表中。

最近,我收到了 ,可以 将其转换为

,所以我决定实现TypeConverter来将JSON字符串转换为自定义C#模型。

不幸的是,当 时,我无法在解决方案中的任何地方使用以下命令来反序列化JSON字符串:

JsonConvert.DeserializeObject<Foo>(json);

删除属性可以解决问题,但是这使我无法将MySQL DB字段转换为自定义C#对象。

这是我的 ,其中添加了TypeConverter属性:

using System.ComponentModel;

[TypeConverter(typeof(FooConverter))]

public class Foo

{

public bool a { get; set; }

public bool b { get; set; }

public bool c { get; set; }

public Foo(){}

}

这是我的 :

using Newtonsoft.Json;

using System;

using System.ComponentModel;

public class FooConverter : TypeConverter

{

public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)

{

if (sourceType == typeof(string))

{

return true;

}

return base.CanConvertFrom(context, sourceType);

}

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

{

if (value is string)

{

string s = value.ToString().Replace("\\","");

Foo f = JsonConvert.DeserializeObject<Foo>(s);

return f;

}

return base.ConvertFrom(context, culture, value);

}

}

}

无法将当前JSON对象(例如{“ name”:“

value”})反序列化为类型’Models.Foo’,因为该类型需要JSON字符串值才能正确反序列化。

要解决此错误,可以将JSON更改为JSON字符串值,或者更改反序列化的类型,使其成为可以反序列化的普通.NET类型(例如,不是整数的原始类型,而不是数组或列表的集合类型)从JSON对象。

还可以将JsonObjectAttribute添加到类型中,以强制其从JSON对象反序列化。

"{\"Foo\":{\"a\":true,\"b\":false,\"c\":false}}"

不知道这是怎么回事,有什么想法吗?

非常感谢!!!

更新

我发现,当 的 ,或者在接受 上,我的操作也存在问题。 *

这是有问题的测试控制器的示例:

public class TestController : ApiController

{

[AcceptVerbs("POST", "GET")]

public void PostTestClass(TestClass t)

{

// Returns null when TypeConverter attribute is added to the Foo Class

return t.Foo;

}

AcceptVerbs("POST", "GET")]

public void PostFooObj(Foo f)

{

// Returns null when TypeConverter attribute is added to the Foo Class

return f;

}

}

当上述任一操作通过具有以下结构的AJAX接收JSON时,TypeConverter可能会导致覆盖WebAPI模型绑定的问题并返回null:

// eg. PostTestClass(TestClass T)

{'Foo': {'a': false,'b': true,'c': false}};

// eg. PostFooObj(Foo f)

{'a': false,'b': true,'c': false}

将TypeConverter属性添加到Foo类时,一旦找到路由,就会调用FooConverter TypeConverter类的以下方法:

    public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)

{

if (sourceType == typeof(string))

{

return true;

}

return base.CanConvertFrom(context, sourceType);

}

FooConverter TypeController上的ConvertFrom方法未由ApiController的操作调用,这可能是问题的原因。

同样,在没有TypeConverter属性的情况下,控制器操作也可以正常工作。

任何进一步的帮助,不胜感激!

非常感谢。

回答:

这里发生了一些事情。首先,一个初步的问题:即使没有TypeConverter应用,您的JSON也不对应于您的class

Foo,它对应于某些包含Foo属性的容器类,例如:

public class TestClass

{

public Foo Foo { get; set; }

}

即给定您的JSON字符串,以下将不起作用:

var json = "{\"Foo\":{\"a\":true,\"b\":false,\"c\":false}}";

var foo = JsonConvert.DeserializeObject<Foo>(json);

但是以下内容将:

var test = JsonConvert.DeserializeObject<TestClass>(json);

我怀疑这只是问题中的一个错误,因此我假设您要反序列化包含property的类Foo

您看到的主要问题是Json.NET

将尝试使用TypeConverterif(如果存在)将要序列化的类转换为JSON字符串。从文档:

.Net :(TypeConverter可转换为String)

JSON:String

但是在您的JSON中,Foo它不是JSON字符串,而是JSON 对象 ,因此一旦应用类型转换器,反序列化将失败。嵌入的字符串如下所示:

{"Foo":"{\"a\":true,\"b\":false,\"c\":false}"}

请注意如何将所有引号转义。并且即使您更改了Foo对象的JSON格式以与此匹配,您的反序列化仍将失败,因为TypeConverterand和Json.NET尝试递归调用彼此。

因此,您需要做的是全局禁用TypeConverterJson.NET的使用,并退回到默认序列化,同时保留TypeConverter在所有其他情况下的使用。这有点棘手,因为没有可用于禁止使用类型转换器的Json.NET属性,而是需要一个特殊的协定解析器以及一个特殊的协定解析器JsonConverter来使用它:

public class NoTypeConverterJsonConverter<T> : JsonConverter

{

static readonly IContractResolver resolver = new NoTypeConverterContractResolver();

class NoTypeConverterContractResolver : DefaultContractResolver

{

protected override JsonContract CreateContract(Type objectType)

{

if (typeof(T).IsAssignableFrom(objectType))

{

var contract = this.CreateObjectContract(objectType);

contract.Converter = null; // Also null out the converter to prevent infinite recursion.

return contract;

}

return base.CreateContract(objectType);

}

}

public override bool CanConvert(Type objectType)

{

return typeof(T).IsAssignableFrom(objectType);

}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)

{

return JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = resolver }).Deserialize(reader, objectType);

}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

{

JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = resolver }).Serialize(writer, value);

}

}

并像这样使用它:

[TypeConverter(typeof(FooConverter))]

[JsonConverter(typeof(NoTypeConverterJsonConverter<Foo>))]

public class Foo

{

public bool a { get; set; }

public bool b { get; set; }

public bool c { get; set; }

public Foo() { }

}

public class FooConverter : TypeConverter

{

public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)

{

if (sourceType == typeof(string))

{

return true;

}

return base.CanConvertFrom(context, sourceType);

}

public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)

{

if (value is string)

{

string s = value.ToString();

//s = s.Replace("\\", "");

Foo f = JsonConvert.DeserializeObject<Foo>(s);

return f;

}

return base.ConvertFrom(context, culture, value);

}

}

小提琴的例子。

最后,您可能还应该ConvertTo在类型转换器中实现该方法,请参见如何:实现类型转换器。

以上是 Newtonsoft.JSON无法使用TypeConverter属性转换模型 的全部内容, 来源链接: utcz.com/qa/432115.html

回到顶部