c# - 使用包含数组的嵌套类进行 JSON 到 C# 的转换
问题描述
总结 MANASYS Jazz 将CICS(= 大型机)Web 服务生成为使用 JSON 进行通信的 COBOL 程序,它还生成相关的 C# 接口,将这些服务作为属性和方法公开给客户端程序。程序 JSPG2 以单个员工记录响应,JSPG2A 是一个最多可以返回 10 条员工记录的版本。JSPG2 完美运行(请参阅此视频),但 JSPG2A 不能。
详细信息 为了将分层 COBOL 记录结构映射到 C# 类,一组嵌套的 C# 类定义如下
namespace MyJSv
{
public class ResponseJSPG2A
{
public class JSPG2AResponse_
{
public class OJSPG2A_
{
//...
public int JZ_Employee_BrowseCount { get; set; }
// and more scalar classes,
public class JZ_Employee_
{
public string JZ_Employee_NthReturnCode { get; set; }
public string EMPNO { get; set; }
// and more classes within the Employee record
}
public JZ_Employee_[] JZ_Employee { get; } = new JZ_Employee_[10];
}
public OJSPG2A_ OJSPG2A { get; } = new OJSPG2A_ ();
}
public JSPG2AResponse_ JSPG2AResponse { get; } = new JSPG2AResponse_ ();
}
}
对于 JZ-Employee 的一次出现,它的定义是
public JZ_Employee_ JZ_Employee { get; } = new JZ_Employee_ ();
否则 ResponseJSPG2 和 ResponseJSPG2A 的定义是一样的
Newtonsoft.JSON 将传入的 JSON 转换为 C#
Response = JsonConvert.DeserializeObject<ResponseJSPG2>(result);
进而
AssignResponseToProperties(true);
将 ResponseJSPG2 中的数据分配给 JSPG2Client 希望公开的属性。
这一切都与 完美配合ResponseJSPG2
,其中有一个员工记录。与<ResponseJSPG2A>
where 有 10 条记录的数组的等效项返回 10 条空记录,而等效项AssignResponseToProperties
在尝试引用 Employee 字段时失败:-
_EMPNO = Response.JSPG2AResponse.OJSPG2A.JZ_Employee[EmployeeSub].EMPNO;
然而,Visual Studio 调试以及使用测试实用程序 ReadyAPI 对 Web 服务程序 JSPG2A 进行的相同测试表明,返回的 JSON 包含 10 条员工记录,所有记录都包含预期的数据。
这是返回给测试的 JSON,经过编辑以删除大部分字段和仅 2 条员工记录,以便它与上面的嵌套 C# 类匹配:-
{
"JSPG2AResponse": {
"OJSPG2A": {
"JZ_Employee_BrowseCount": 16,
"JZ_Employee": [
{
"JZ_Employee_NthReturnCode": "F",
"EMPNO": "000060"
},
{
"JZ_Employee_NthReturnCode": "N",
"EMPNO": "000090"
}
]
}
}
}
问题
有没有办法让 DeserializeObject 自动处理数组类,还是我必须使用 Newtonsoft.Json.Linq 并编写逻辑来解析 JSON 并显式处理数组?或者其他实现我目标的方法?
解决方案
您的问题是该JZ_Employee
属性是一个缺少 setter的数组值属性:
public JZ_Employee_[] JZ_Employee { get; } = new JZ_Employee_[10];
因为 .Net 数组无法调整大小,Json.NET 将它们视为只读集合,其内容需要累积到临时列表中,然后用于构造数组并将其设置回其父级。但是,您的数组属性没有设置器,因此 Json.NET 将其视为完全只读并完全跳过它。
要解决此问题,您可以添加一个 setter。可能是protected
或者private
如果您使用以下标记属性[JsonProperty]
:
[JsonProperty]
public JZ_Employee_[] JZ_Employee { get; private set; } = new JZ_Employee_[10];
演示小提琴#1在这里。
或者,您可以将属性保留为 get-only,但将数组替换为可调整大小的集合,例如List<JZ_Employee_>
:
public List<JZ_Employee_> JZ_Employee { get; } = new List<JZ_Employee_>();
演示小提琴#2在这里。
第二个选项的优点是您可以应用[JsonConverter(typeof(SingleOrArrayConverter<JZ_Employee_>))]
或仅从如何使用 JSON.net to处理同一属性的单个项目和数组的[JsonConverter(typeof(SingleOrArrayListConverter))]
答案中应用,这将允许您合并和类:JZ_Employee
ResponseJSPG2
ResponseJSPG2A
[JsonConverter(typeof(SingleOrArrayConverter<JZ_Employee_>))]
public List<JZ_Employee_> JZ_Employee { get; } = new List<JZ_Employee_>();
转换器会自动将单个JZ_Employee
对象的大小写转换为包含一项的列表。
推荐阅读
- python - 我怎样才能摆脱这个小的逻辑错误?
- django - 从数据库中获取字段数据以填充已提交表单的用户的表单字段
- c# - c# 使用泛型访问表
- r - 在 R 中调用函数中的变量时出错
- python - 在python的netCDF文件中提取特定纬度/经度上的传感日期/时间
- javascript - AMCharts Force Directed Tree 向子级添加 javascript 函数
- javascript - 如何使用 JavaScript 在链中使用 firebase onSnapshot?
- python-3.x - 无法使用 Python 3.7.5 在 Ubuntu 18.04 上安装 grpcio?
- java - 使用 DOM 在 Java 中将 XML 转换为 csv
- java - 子阵列最大乘积的 Kadenes 算法。帮我找出我的代码中的错误