如何使用Json.NET中的JsonSerializerSettings在属性中指定TypeNameHandling



有时我需要通过Json.NET抑制"$type"属性的输出,即使是在由JsonPropertyAttribute.ItemTypeNameHandling指定的情况下也是如此。如何做到这一点?

我的根类如下所示:

public class DomainResource
{
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
public List<Extension> Extensions { get; set; }
}

此外,我还有一个Extension的类层次结构,如下所示:

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设置JsonSerializerSettings.None作为jsonconvert的输入,使用以下代码:

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);
}

然后按如下方式使用:

var res = new DomainResource();
res.Extensions = new List<Extension>();
res.Extensions.Add(new IntegerExtension("ewwer"){Value = 3});
var x = CustomJsonConvert.SerializeObject(res);

我想要的JSON是:

{"extensions":〔{"valueInteger":3,"url":"ewwer"}〕}

但它包含"$type"属性,如下所示:

{"extensions":[{"$type":"DicomtoJsonConverter.IntegerExtension,DicomtoJsonConverter","valueInteger":3,"url":"ewwer"}]}

如何在不更改DomainResource类的情况下抑制"$type"属性的输出?

即使由JsonPropertyAttribute.TypeNameHandlingJsonPropertyAttribute.ItemTypeNameHandlingJsonContainerAttribute.ItemTypeNameHandling指定,也可以使用自定义ContractResolver来抑制类型信息的输出。首先,定义以下合同解析器:

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是在该版本中引入的。

相关内容

  • 没有找到相关文章

最新更新