问题描述
有时,即使由 JsonPropertyAttribute.ItemTypeNameHandling
.该怎么办?
Sometimes I need to suppress output of "$type"
properties by Json.NET even when specified by JsonPropertyAttribute.ItemTypeNameHandling
. How can this be done?
我的根类如下:
public class DomainResource
{
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
public List<Extension> Extensions { get; set; }
}
此外,我还有Extension
的类层次结构,如下所示:
And in addition I have a class hierarchy for Extension
such as the following:
public class Extension
{
readonly string url;
public string Url { get { return url; } }
public Extension(string url)
{
this.url = url;
}
}
public class IntegerExtension : Extension
{
public IntegerExtension(string url) : base(url) { }
[JsonProperty("ValueInteger")]
public int Value { get; set; }
}
在序列化过程中的某些情况下,我想忽略ItemTypeNameHandling
,但是我找不到解决方法.当我不想要使用以下代码的"$type"
属性时,我尝试使用TypeNameHandling.None作为JsonConvert的输入来设置JsonSerializerSettings.
I want to ignore ItemTypeNameHandling
in certain scenarios during serialization, but I am not able to find a way to do that. I tried setting JsonSerializerSettings with TypeNameHandling.None as input for jsonconvert when I do not want "$type"
properties using the code below:
public static string SerializeObject(object value)
{
JsonSerializerSettings jsonSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.None,
};
jsonSettings.Converters.Add(new StringEnumConverter
{
CamelCaseText = true
});
return JsonConvert.SerializeObject(value, Formatting.None, jsonSettings);
}
然后按如下所示使用它:
And then use it as follows:
var res = new DomainResource();
res.Extensions = new List<Extension>();
res.Extensions.Add(new IntegerExtension("ewwer"){Value = 3});
var x = CustomJsonConvert.SerializeObject(res);
我想要的JSON是:
但是它包含如下所示的"$type"
属性:
But instead it contains "$type"
properties as shown below:
如何在不更改DomainResource
类的情况下抑制"$type"
属性的输出?
How can I suppress output of "$type"
properties without changing DomainResource
class?
推荐答案
您可以使用自定义ContractResolver
来抑制类型信息的输出,即使由 JsonPropertyAttribute.TypeNameHandling
, JsonPropertyAttribute.ItemTypeNameHandling
或 JsonContainerAttribute.ItemTypeNameHandling
.首先,定义以下合同解析器:
You can use a custom ContractResolver
to suppress output of type information even when specified by JsonPropertyAttribute.TypeNameHandling
, JsonPropertyAttribute.ItemTypeNameHandling
or JsonContainerAttribute.ItemTypeNameHandling
. First, define the following contract resolver:
public class NoTypeNameHandlingContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
// Suppress JsonPropertyAttribute.TypeNameHandling
property.TypeNameHandling = null;
// Suppress JsonPropertyAttribute.ItemTypeNameHandling
property.ItemTypeNameHandling = null;
return property;
}
protected override JsonContract CreateContract(Type objectType)
{
var contract = base.CreateContract(objectType);
if (contract is JsonContainerContract)
{
// Suppress JsonContainerAttribute.ItemTypeNameHandling
((JsonContainerContract)contract).ItemTypeNameHandling = null;
}
return contract;
}
}
然后,如下修改CustomJsonConvert.SerializeObject()
:
public static class CustomJsonConvert
{
// You may want to cache the contract resolver for best performance, see
// https://stackoverflow.com/questions/33557737/does-json-net-cache-types-serialization-information
static readonly JsonSerializerSettings jsonSettings;
static CustomJsonConvert()
{
jsonSettings = new JsonSerializerSettings
{
ContractResolver = new NoTypeNameHandlingContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy
{
// These are the settings used by CamelCasePropertyNamesContractResolver by default.
// Change them if this is not what you want.
OverrideSpecifiedNames = true,
ProcessDictionaryKeys = true,
},
},
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.None,
Converters = { new StringEnumConverter { CamelCaseText = true } },
};
}
public static string SerializeObject(object value)
{
return JsonConvert.SerializeObject(value, Formatting.None, jsonSettings);
}
}
如果您使用的Json.NET版本早于 9.0 .1 您需要将CamelCasePropertyNamesContractResolver
子类化,而不是将DefaultContractResolver
子类化,因为 NamingStrategy
.
If you are using a version of Json.NET that predates 9.0.1 you will need to subclass CamelCasePropertyNamesContractResolver
rather than subclassing DefaultContractResolver
since NamingStrategy
was introduced in that release.
这篇关于通过使用Json.NET中的JsonSerializerSettings在属性中指定时如何禁用TypeNameHandling?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!