- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 Newtonsoft.Json.Schema。似乎 Newtonsoft 的 JsonConvert
无法反序列化它自己的 ValidationError
.
具体来说,以下将失败:
var dataFile = System.IO.File.ReadlAllText("data.json");
var schemaFile = System.IO.File.ReadlAllText("schema.json");
... // parsing the files
model.IsValid(schema, out IList<Newtonsoft.Json.Schema.ValidationError> ve);
var errors = ve as List<Newtonsoft.Json.Schema.ValidationError>; // <-- this may be a problem?
var resultStr = Newtonsoft.Json.JsonConvert.SerializeObject(errors); // <-- this works as expected, though
var ReSerializedResult = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Newtonsoft.Json.Schema.ValidationError>>(resultStr);
我在序列化后得到了一个有效的 resultStr 字符串,类似于
[{\"Message\": \"String 'key' does not match regex pattern ... \", ... }]
再次反序列化后,我得到了一个类型为 Newtonsoft.Json.Schema.ValidationError 的项目的数组(验证结果有一个错误所以没关系),但它的所有字段都是默认值。
有没有其他人也遇到过这个?有没有办法使用 Json.NET 往返 ValidationError
,或者我应该在其 GitHub issues page 上打开一个问题?
最佳答案
您在这里遇到了几个问题。
首先,ValidationError
是公开不可变的(即所有属性都缺少公共(public) setter )并且只有一个构造函数,即 nonparameterized .因此第三方应用程序(包括 Json.NET 本身)无法填充此类型的实例。
reference source然而,显示大多数属性都有私有(private) setter 。因此,应该可以从 this answer 中调整 SisoJsonDefaultContractResolver
通过 daniel给 Private setters in Json.Net 到往返 ValidationError
。首先定义:
public class SelectedPrivateSettersContractResolver : DefaultContractResolver
{
HashSet<Type> privateSetterTypes { get; } = new ();
public SelectedPrivateSettersContractResolver(params Type [] types) : this((IEnumerable<Type>)types) { }
public SelectedPrivateSettersContractResolver(IEnumerable<Type> types) =>
privateSetterTypes.UnionWith(types ?? throw new ArgumentNullException());
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
if (!prop.Ignored && prop.Readable && !prop.Writable)
if (privateSetterTypes.Contains(prop.DeclaringType))
if (member is PropertyInfo property)
prop.Writable = property.GetSetMethod(true) != null;
return prop;
}
}
现在您可以:
var settings = new JsonSerializerSettings
{
ContractResolver = new SelectedPrivateSettersContractResolver(typeof(ValidationError)),
};
var resultStr = JsonConvert.SerializeObject(errors, Formatting.Indented, settings);
var ReSerializedResult = JsonConvert.DeserializeObject<List<ValidationError>>(resultStr, settings);
演示 fiddle #1 here .
但是,虽然这允许大多数 ValidationError
属性成功往返,但 Message
属性却不能。第二个问题的出现是因为,在当前的实现中,Message
没有 setter/getter 。相反,它返回按需计算的字段 _message
的值。因此,有必要强制序列化 _message
(以及相关字段 _extendedMessage
)。 custom contract resolver继承自 SelectedPrivateSettersContractResolver
可用于执行此操作:
public class ValidationErrorsContractResolver : SelectedPrivateSettersContractResolver
{
static readonly string [] validationErrorFields = new [] { "_message", "_extendedMessage" };
public ValidationErrorsContractResolver() : base(typeof(ValidationError)) { }
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var list = base.GetSerializableMembers(objectType);
if (typeof(ValidationError).IsAssignableFrom(objectType))
{
foreach (var fieldName in validationErrorFields)
if (objectType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) is var f && f != null)
list.Add(f);
}
return list;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
if (prop.DeclaringType == typeof(ValidationError))
{
if (validationErrorFields.Contains(prop.UnderlyingName))
{
prop.Ignored = false;
prop.Readable = prop.Writable = true;
}
}
return prop;
}
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
if (typeof(ValidationError).IsAssignableFrom(objectType))
{
// Ensure _message and _extendedMessage are calculated.
contract.OnSerializingCallbacks.Add((o, c) => { var m = ((ValidationError)o).Message; });
}
return contract;
}
}
现在如果你按如下方式往返:
var settings = new JsonSerializerSettings
{
ContractResolver = new ValidationErrorsContractResolver(),
};
var resultStr = JsonConvert.SerializeObject(errors, Formatting.Indented, settings);
var ReSerializedResult = JsonConvert.DeserializeObject<List<ValidationError>>(resultStr, settings);
消息成功往返。演示 fiddle #2 here .
注意事项:
以这种方式使用反射强制序列化私有(private)字段是脆弱的,如果 Newtonsoft 更改 ValidationError
的实现,可能很容易崩溃。
您可能想要缓存和重用 ValidationErrorsContractResolver
以获得最佳性能,如 the documentation 中所建议的那样.
您可能会注意到第三个问题,即 Schema
ValidationError
的属性未被序列化或反序列化,因为 Newtonsoft 已在 source code 中用 [JsonIgnore]
明确标记它.我怀疑他们这样做是为了防止序列化的 JSON 变得过于臃肿。如果您希望 Schema
进行往返,您可以在 ValidationErrorsContractResolver.CreateProperty()
中强制将其序列化,如下所示:
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
if (prop.DeclaringType == typeof(ValidationError))
{
if (validationErrorFields.Contains(prop.UnderlyingName)
|| prop.UnderlyingName == "Schema")
{
prop.Ignored = false;
prop.Readable = prop.Writable = true;
}
}
return prop;
}
但是,如果这样做,您的 JSON 将变得更加臃肿,并且如果您序列化多个验证错误,JSchema Schema
值将在反序列化过程中重复,因为它未通过引用保存。
演示 fiddle #3 here .
关于c# - newtonsoft json 模式反序列化 ValidationError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66136063/
我正在阅读 Python 文档以真正深入了解 Python 语言,并遇到了 filter 和 map 函数。我以前使用过过滤器,但从未使用过映射,尽管我在 SO 上的各种 Python 问题中都见过这
当我尝试打印 BST 的级别顺序时,这个问题提示了我。 这是一个 Pre-Order Sequence: 4, 1, 2, 3, 5, 6, 7, 8 In_order Sequence : 1, 2
我的代码在 main(序列测试;)的第一行出现错误,指出它是对 sequence::sequence() 的 undefined reference 。我无法更改 main 中的代码。有谁知道我该如何
这可能很简单,但我在通常的 latex 指南中找不到任何相关内容。在这句话中: {\em hello\/} “\/”的目的是什么? 最佳答案 这就是所谓的斜体校正。其目的是确保斜体文本后有适当的间距。
当我从 Postgresql 表中删除所有记录,然后尝试重置序列以在插入时开始一个编号为 1 的新记录时,我得到不同的结果: SELECT setval('tblname_id_seq', (SELE
在版本10.0.3中,MariaDB引入了一种称为序列的存储引擎。 其ad hoc为操作生成整数序列,然后终止。 该序列包含正整数,以降序或升序排列,并使用起始,结束和递增值。 它不允许在多个查询中
如何在 Groovy 中获取给定数字的序列,例如: def number = 169 // need a method in groovy to find the consecutive number
基本上,如果这是 .NET,它看起来像这样: ISomething { string A { get; } int B { get; } } var somethings = new List
说以下代码部分(同一块): A <= 1 A <= 2 变量 A 总是被赋值为 2 吗?还是会出现竞争条件并分配 1 或 2? 我对非阻塞赋值的理解是,由硬件在 future 分配变量 A,因此它可能
在运行 WiX 设置时,我正在寻找操作列表及其顺序。不知何故,官方网站似乎没有提供任何信息。 基本问题是我想正确安排我的自定义操作。通常我需要使用 regsvr32.exe 注册一个 DLL,而这只能
F#初学者在这里 我想创建一个类型,它是具有至少一个元素的另一种具体类型(事件)的序列。任何其他元素都可以在以后随时添加。通常在 C# 中,我会创建一个具有私有(private) List 和公共(p
作为构建过程和不断发展的数据库的一部分,我试图创建一个脚本,该脚本将删除用户的所有表和序列。我不想重新创建用户,因为这将需要比所允许的更多的权限。 我的脚本创建了一个过程来删除表/序列,执行该过程,然
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
这个问题已经有答案了: sql ORDER BY multiple values in specific order? (12 个回答) 已关闭 9 年前。 我有一个 sql 语句,我想要ORDER
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
在用java编写代码时,我需要用“],[”分割字符串。下面是我的代码。 try (BufferedReader reader = new BufferedReader(new InputStreamR
这个问题已经有答案了: Project Euler Question 14 (Collatz Problem) (8 个回答) 已关闭 9 年前。 我正在尝试查找数字的 Collatz 序列。以下
我有一个例程函数process_letter_location(const char& c, string &word)。 在我的 main 中,我声明了一系列字符串变量,如下所示: string s
我需要找到最长的多米诺骨牌链,给定一组 12 个随机挑选的多米诺骨牌。我已经递归地生成了多米诺骨牌的所有可能性(使用 0 到 12 的面值有 91 种可能性)。多米诺骨牌由一 block “砖 blo
我有这个数据结构 Seq,它继承了类 vector 但有一些额外的功能。使用这个数据结构 Seq 我有这个预定义的数据结构: typedef Seq > MxInt2d; 我现在想要一个包含多个 Mx
我是一名优秀的程序员,十分优秀!