c# - 如果已在“[JsonProperty]”中定义,我可以通过其属性名称获取属性吗?
问题描述
我正在开发一个用于 JSON 序列化的 C# 程序。
我的对象如下所示(属性示例):
public class Device
{
[JsonProperty("ALLTYPES_NAME")]
public string ALLTYPES_NAME { get; set; }
[JsonProperty("INFORMATION")]
public string INFORMATION { get; set; }
...
现在我有以下信息(在文本文件中):
ALLTYPES_NAME "Object1"
ALLTYPES_NAME "Object2"
INFORMATION "Inside_Info"
我想创建两个对象,它们将被 JSON 序列化如下:
"desired_objects": [
{
"ALLTYPES_NAME": "Object1",
},
{
"ALLTYPES_NAME": "Object2",
"INFORMATION": "Inside_Info,
...
为了完成这项工作,我需要类似的东西:
temp_obj.GetPropertyByName("ALLTYPES_NAME") = "Object1";
desired_objects.Add(temp_obj);
...
temp_obj.GetPropertyByName("ALLTYPES_NAME") = "Object2";
temp_obj.GetPropertyByName("INFORMATION") = "Inside_Information";
...
一种方法是使用模板。但是我想知道这是否需要,看到所需信息可以使用[JsonProperty]
指令检索的事实,因此我的问题是:
是否.GetPropertyByName()
存在基于[JsonProperty ...]
? (或者更大,这些[JsonProperty]
指令可以用于其他东西而不是 JSON 序列化器吗?)
解决方案
您可以使用 Json.NET为您的对象IContractResolver
获取一个包含有关该类型的所有属性(包括其 JSON 名称和 get/set 方法)的信息。以下扩展方法可以解决问题:JsonObjectContract
Device
public static partial class JsonExtensions
{
static readonly IContractResolver defaultResolver = JsonSerializer.CreateDefault().ContractResolver;
public static void SetJsonProperty<T>(T obj, string jsonName, object value, bool exact = false, IContractResolver resolver = null)
{
if (!TrySetJsonProperty(obj, jsonName, value, exact, resolver))
throw new ArgumentException(string.Format("Could not set property {0} in {1}.", jsonName, obj));
}
public static bool TrySetJsonProperty<T>(T obj, string jsonName, object value, bool exact = false, IContractResolver resolver = null)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
resolver = resolver ?? defaultResolver;
var contract = resolver.ResolveContract(obj.GetType()) as JsonObjectContract;
if (contract == null)
return false;
var property = contract.Properties.GetProperty(jsonName, exact ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
if (property == null || !property.Writable)
return false;
property.ValueProvider.SetValue(obj, value);
return true;
}
}
此外,如果您从文本文件中读取并且某些属性值类型不是字符串,则需要将文本值从文件转换为适当的 .Net 类型。以下是这样做的:
public static partial class JsonExtensions
{
public static void SetConvertibleJsonProperty<T, TConvertible>(T obj, string jsonName, TConvertible value, bool exact = false, IContractResolver resolver = null) where TConvertible : IConvertible
{
if (!TrySetConvertibleJsonProperty(obj, jsonName, value, exact, resolver))
throw new ArgumentException(string.Format("Could not set property {0} in {1}.", jsonName, obj));
}
public static bool TrySetConvertibleJsonProperty<T, TConvertible>(T obj, string jsonName, TConvertible value, bool exact = false, IContractResolver resolver = null)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
resolver = resolver ?? defaultResolver;
var contract = resolver.ResolveContract(obj.GetType()) as JsonObjectContract;
if (contract == null)
return false;
var property = contract.Properties.GetProperty(jsonName, exact ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
if (property == null || !property.Writable)
return false;
var finalValue = value == null ? null : Convert.ChangeType(value, Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType, CultureInfo.InvariantCulture);
property.ValueProvider.SetValue(obj, finalValue);
return true;
}
}
要使用它,请执行以下操作:
JsonExtensions.SetConvertibleJsonProperty(temp_obj, "ALLTYPES_NAME", "Object1");
JsonExtensions.SetConvertibleJsonProperty(temp_obj, "ALLTYPES_NAME", "Object2");
JsonExtensions.SetConvertibleJsonProperty(temp_obj, "INFORMATION", "Inside_Information");
// The following sets the following property
// [JsonProperty("DECIMAL_DATA")]
// public decimal DecimalInformation { get; set; }
JsonExtensions.SetConvertibleJsonProperty(temp_obj, "DECIMAL_DATA", "3.1111");
笔记:
CamelCasePropertyNamesContractResolver
如果您使用驼峰式大小写进行序列化和反序列化,请传递IContractResolver resolver
参数。该方法不适用于动态对象或字典。
有关通过 JSON 属性名称获取属性值的等效方法,请参阅如何使用 C# 中的反射获取 Json 属性名称的答案。
演示小提琴在这里。
推荐阅读
- java - 使用 OneToMany 标签时.. EntityManager 没有持久性提供程序 - Hibernate JPA
- reactjs - FileReader - 存储更新后如何更新本地状态?
- javascript - Puppeteer.js:获取带有给定文本的链接的 href 属性
- javascript - 如何在 React 中访问其他组件的数据
- excel - 在 Excel VBA 中使用变量设置范围
- python - 匹配有效列表
- azure-pipelines - 构建和发布工件任务问题
- python - 给定一个字符串如何在python中查找所有非空白子字符串的开始和结束索引
- json - Eloquent Accessor:更新模型实例的属性
- netsuite - NetSuite 高级 PDF/HTML 富文本渲染 - 意外错误