提问人:user1615351 提问时间:8/3/2021 最后编辑:user1615351 更新时间:8/4/2021 访问量:570
PropertyInfo getProperty() 方法的问题
Issue with PropertyInfo getProperty() Method
问:
request.Data
{
"jurisdictionCode": "California",
"claimId": 123654,
"claimGroupID": 12,
"claimXref": "32145",
"serviceXref": "Test",
"claimStart": "2021-07-30T13:20:15.338Z",
"claimEnd": "2021-07-30T13:20:15.338Z",
"status": 5,
"creationTimestamp": "2021-07-30T13:20:15.338Z",
"touchTimestamp": "2021-07-30T13:20:15.338Z",
"filingSource": 7,
"userName": "test",
"exportTs": "2021-07-30T13:20:15.338Z",
"payerXref": "test",
"dtbatchExportTs": "2021-07-30T13:20:15.338Z"
}
public class scaffolded_model
{
[Key]
[StringLength(10)]
public string JurisdictionCode { get; set; }
[Key]
public long ClaimID { get; set; }
public long ClaimGroupID { get; set; }
[Required]
[StringLength(64)]
public string ClaimXRef { get; set; }
[Required]
[StringLength(64)]
public string ServiceXRef { get; set; }
[Column(TypeName = "datetime")]
public DateTime ClaimStart { get; set; }
[Column(TypeName = "datetime")]
public DateTime ClaimEnd { get; set; }
public int Status { get; set; }
[Column(TypeName = "datetime")]
public DateTime CreationTimestamp { get; set; }
[Column(TypeName = "datetime")]
public DateTime TouchTimestamp { get; set; }
public int FilingSource { get; set; }
[Required]
[StringLength(256)]
public string UserName { get; set; }
[Key]
[Column(TypeName = "datetime")]
public DateTime ExportTS { get; set; }
[Required]
[StringLength(64)]
public string PayerXRef { get; set; }
[Column(TypeName = "datetime")]
public DateTime DTBatchExportTS { get; set; }
}
法典:
var data = JsonSerializer.Serialize(request.Data);
Dictionary<string, JsonElement> result = (Dictionary<string, JsonElement>)JsonSerializer.Deserialize(data, typeof(Dictionary<string, JsonElement>));
foreach (var item in result)
{
PropertyInfo pi = scaffolded_model
.GetType()
.GetProperty(item.Key, BindingFlags.Instance | BindingFlags.Public);
if (pi == null)
{
_logger.LogInformation("Bad Field");
continue;
}
pi.SetValue(scaffolded_model, item.Value);
}
我在使用 GetProperty() 方法匹配和填充作为请求传入的 json 请求中的值时遇到了问题。数据和一个名为 scaffolded_model 的空模型。据我所知,两组数据都设置正确。代码应遍历请求中的每个值,通过在空模型中item.key来匹配它,并使用该值填充匹配键。item.key每次都是空的。我尝试了不同的绑定等。如果我将第一个item.key硬编码为 JurisdictionCode,它会获取该值并正确填充它。因此,如果item.key会填充,一切都在工作。
感谢您的寻找和所有帮助。
[ApiVersion("1.0")]
[HttpPost("v{version:apiVersion}/Submitclaim")]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public Task<IActionResult> Submitclaim(ClaimModel request)
{
var source = MethodBase.GetCurrentMethod().Name;
IActionResult actionResult = null;
using (LogContext.PushProperty("jx", request.JurisdictionCode))
{
try
{
//var claim_data = JsonSerializer.Serialize(request);
//Dictionary<string, JsonElement> result = (Dictionary<string, JsonElement>)JsonSerializer.Deserialize(claim_data, typeof(Dictionary<string, JsonElement>));
API.CRUD.Claims.Model.Claim scaffolded_model = new API.CRUD.Claims.Model.Claim();
JsonSerializer.Deserialize<scaffolded_model>(request);
//foreach (var item in result)
//{
// PropertyInfo pi = scaffolded_model
// .GetType()
// .GetProperty(
// item.Key,
// BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
// if (pi == null)
// {
// _logger.LogInformation("Bad Field");
// continue;
// }
// pi.SetValue(
// scaffolded_model,
// Convert.ChangeType(item.Value.ToString(), pi.PropertyType));
//}
}
catch (Exception ex)
{
_logger.LogError($"Exception failed: {ex.Message}");
actionResult = Problem("Exception failed");
}
}
return Task.FromResult(actionResult);
}
答:
如果您有充分的理由通过 Reflection 而不是使用标准的 System.Text.Json 或 Newtonsoft.Json 库来实现自定义 JSON 解析,那么有几个问题需要解决:
- Type.GetProperty 区分大小写。默认情况下,它不会将属性名称与属性匹配。
BindingFlags.IgnoreCase
标志应该可以解决此问题。jurisdictionCode
JurisdictionCode
PropertyInfo pi = scaffolded_model
.GetType()
.GetProperty(
item.Key,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
- 第二个问题与类型转换有关。
PropertyInfo.SetValue
不执行任何类型转换。需要设置的值必须与属性类型匹配,否则将被抛出。此时,问题中的代码始终将方法返回的字符串值设置为所有属性。它不适用于 或 属性。若要解决此问题,可以将 Convert.ChangeType
方法用作处理类中定义的属性类型的最简单选项。TargetException
item.Value.ToString()
long
DateTime
scaffolded_model
pi.SetValue(
scaffolded_model,
Convert.ChangeType(item.Value.ToString(), pi.PropertyType));
通过这两项更改,可以解析 Json 表单示例。
但当前代码有一些局限性:
它不处理 null。如果是字符串属性,则空字符串值将分配给该属性,而不是原始的 null 值。完全不支持可为 null 的值类型(例如 long?)。若要解决此问题,可以调整当前逻辑以检查属性的值。
JsonElement.ValueKind
JsonValueKind.Null
另一个问题是类型。在当前的实现中,所有值都将调整为本地时区,并且 method 不提供任何控制它的能力。替换时间将不起作用,因为方法不支持它。只有检查属性类型和执行手动转换的选项,例如,使用 method 而不是 。
DateTime
DateTime
Convert.ChangeType
DateTime
DateTimeOffset
Convert.ChangeType
DateTime.Parse
Convert.ChangeType
此列表可以继续。所以一般情况下,最好使用标准库来解析Json。
评论
API.CRUD.Claims.Model.Claim scaffolded_model = JsonSerializer.Deserialize<API.CRUD.Claims.Model.Claim>(jsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
PropertyNameCaseInsensitive
评论
scaffolded_model
JsonSerializer.Deserialize<scaffolded_model>(data)
item.Value.ToString()
item.Value
JsonSerializer.Deserialize<scaffolded_model>(data)