如果已在 "[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]指令检索的事实,因此我的问题:

是否存在基于[JsonProperty ...]的方法.GetPropertyByName()?(或者更大,[JsonProperty]指令可以用于其他东西而不是JSON序列化器吗?)

可以使用Json。. NET的IContractResolver为您的Device对象获取JsonObjectContract,该对象包含有关该类型的所有属性的信息,包括其JSON名称和get/set方法。下面的扩展方法可以做到这一点:

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");  

指出:

  • 如果使用驼峰大小写进行序列化和反序列化,则为IContractResolver resolver参数传递CamelCasePropertyNamesContractResolver

  • 该方法不是为动态对象或字典设计的。

  • 关于通过JSON属性名获取属性值的等效方法,请参见如何在c#中使用反射获取JSON属性名

此处演示小提琴

经过一些实验,根据Jon Skeet的评论,我意识到我甚至不需要JSON指令,正如您可以从以下代码摘录中看到的:

System.Reflection.PropertyInfo[] list_of_attributes = 
(new Own_Class()).GetType().GetProperties();
string[] list_of_attribute_names = new string[list_of_attributes.Length];
for (int i = 0; i< list_of_attributes.Length; i++)
list_of_attribute_names[i] = list_of_attributes[i].Name;
combobox_on_form.Items.AddRange(list_of_attribute_names);

相关内容

  • 没有找到相关文章

最新更新