数据结构蓝图:
public class Movie
{
public string Name { get; set; }
}
使用Newtonsoft.Json,我有以下Json序列化配置。
var settings = new JsonSerializerSettings() {
ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
显然,这将打印出来:
{
name: null
}
现在,我需要在JsonSerializerSettings中向ContractResolver添加另一个NullToEmptyStringResolver,如何实现以下输出:
{
name: ""
}
答案 0 :(得分:11)
Json.Net一次不允许多个合同解析器,因此您需要一种方法来组合他们的行为。我假设NullToEmptyStringResolver
是一个自定义解析器,它继承自Json.Net的DefaultContractResolver
类。如果是这样,实现所需结果的一种简单方法是改为NullToEmptyStringResolver
继承CamelCasePropertyNamesContractResolver
。
public class NullToEmptyStringResolver : CamelCasePropertyNamesContractResolver
{
...
}
如果您不喜欢这种方法,另一个想法是将骆驼套管行为添加到NullToEmptyStringResolver
。如果你看一下source code中CamelCasePropertyNamesContractResolver
的实现方式,你会发现这就像在构造函数中设置NamingStrategy
一样简单(假设你使用的是Json)。 Net 9.0.1或更高版本)。您可以将相同的代码添加到NullToEmptyStringResolver
的构造函数中。
public class NullToEmptyStringResolver : DefaultContractResolver
{
public NullToEmptyStringResolver() : base()
{
NamingStrategy = new CamelCaseNamingStrategy
{
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
};
}
...
}
答案 1 :(得分:3)
我发现创建复合合约解析器更好。这就是我在项目中使用的内容:
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();
}
}
然后我就这样使用它:
Settings = new JsonSerializerSettings
{
ContractResolver = new CompositeContractResolver
{
new InterfaceContractResolver<ISomething>(),
new DefaultContractResolver()
}
}
我的自定义合约解析器会返回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;
}
}
答案 2 :(得分:2)
这是另一种选择。您可以使用NamingStrategy
代替CamelCasePropertyNamesContractResolver
,而不是使用两个ContractResolvers。
var settings = new JsonSerializerSettings()
{
ContractResolver = new NullToEmptyStringResolver(){NamingStrategy = new CamelCaseNamingStrategy()}
};
这是类似@ BrianRogers的第二种方法。我刚刚没有将设置硬编码为NullToEmptyStringResolver
类。