数据结构蓝图:
public class Movie
{
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
使用Newtonsoft.Json,我有以下Json序列化配置.
var settings = new JsonSerializerSettings() {
ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
Run Code Online (Sandbox Code Playgroud)
显然,这将打印出来:
{
name: null
}
Run Code Online (Sandbox Code Playgroud)
现在,我需要另一个NullToEmptyStringResolver添加到JsonSerializerSettings的ContractResolver,我怎么能做到这一点,其下面的输出:
{
name: ""
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*ers 12
Json.Net一次不允许多个合同解析器,因此您需要一种方法来组合他们的行为.我假设这NullToEmptyStringResolver是一个继承自Json.Net DefaultContractResolver类的自定义解析器.如果是这样,实现所需结果的一种简单方法是改为NullToEmptyStringResolver继承CamelCasePropertyNamesContractResolver.
public class NullToEmptyStringResolver : CamelCasePropertyNamesContractResolver
{
...
}
Run Code Online (Sandbox Code Playgroud)
如果您不喜欢这种方法,另一个想法是将骆驼套管行为添加到您的NullToEmptyStringResolver.如果你看看如何CamelCasePropertyNamesContractResolver在实现源代码,你会看到这是设置简单NamingStrategy的构造函数(假设你使用Json.Net 9.0.1或更高版本).您可以将相同的代码添加到您的构造函数中NullToEmptyStringResolver.
public class NullToEmptyStringResolver : DefaultContractResolver
{
public NullToEmptyStringResolver() : base()
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
};
}
...
}
Run Code Online (Sandbox Code Playgroud)
我发现创建一个复合合同解析器是一个更好的主意。这是我在项目中使用的:
public class CompositeContractResolver : IContractResolver, IEnumerable<IContractResolver>
{
private readonly IList<IContractResolver> _contractResolvers = new List<IContractResolver>();
public JsonContract ResolveContract(Type type)
{
return
_contractResolvers
.Select(x => x.ResolveContract(type))
.FirstOrDefault(Conditional.IsNotNull);
}
public void Add([NotNull] IContractResolver contractResolver)
{
if (contractResolver == null) throw new ArgumentNullException(nameof(contractResolver));
_contractResolvers.Add(contractResolver);
}
public IEnumerator<IContractResolver> GetEnumerator()
{
return _contractResolvers.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我像这样使用它:
Settings = new JsonSerializerSettings
{
ContractResolver = new CompositeContractResolver
{
new InterfaceContractResolver<ISomething>(),
new DefaultContractResolver()
}
}
Run Code Online (Sandbox Code Playgroud)
我的自定义合同解析器在其中返回了null一份合同,因此如果没有匹配项,则复合合同可以通过默认合同。
public class InterfaceContractResolver<T> : DefaultContractResolver
{
public InterfaceContractResolver()
{
if (!typeof(T).IsInterface) throw new InvalidOperationException("T must be an interface.");
}
public override JsonContract ResolveContract(Type type)
{
return
typeof(T).IsAssignableFrom(type)
? base.ResolveContract(typeof(T))
: default;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return
typeof(T).IsAssignableFrom(type)
? base.CreateProperties(typeof(T), memberSerialization)
: default;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个替代方案。除了使用两个 ContractResolver,您还可以使用NamingStrategy代替CamelCasePropertyNamesContractResolver.
var settings = new JsonSerializerSettings()
{
ContractResolver = new NullToEmptyStringResolver(){NamingStrategy = new CamelCaseNamingStrategy()}
};
Run Code Online (Sandbox Code Playgroud)
这是类似@BrianRogers 的第二种方法。我只是没有将设置硬编码到NullToEmptyStringResolver课堂上。
| 归档时间: |
|
| 查看次数: |
4728 次 |
| 最近记录: |