【问题标题】:How to convert json from array of properties如何从属性数组转换json
【发布时间】:2023-03-16 01:48:01
【问题描述】:

我想知道是否有任何开箱即用的功能可以将以下 json 转换为对象,或者我是否需要为这种类型的 JSON 对象开发自己的反序列化器?

{
   "Fields":[
      "Code",
      "Name"
   ],
   "Records":[
      [
         "JD",
         "Jhon Doe"
      ],
      [
         "JJ",
         "Jhon Joe"
      ]
   ]
}

对象

public class Response
{
    public string[] Fields { get; set; }
    public Something[] Records { get; set; }
}

public class Something {
    public string Code { get; set; }
    public string Name { get; set; }
}

【问题讨论】:

标签: c# json json.net


【解决方案1】:

我猜,棘手的部分是您将Records 作为字符串数组的数组,因此没有分别映射到CodeName

如果您可以在结果对象中没有 CodeName 属性的情况下工作,您可以这样定义它:

public class Response
{
    public string[] Fields { get; set; }
    public string[][] Records { get; set; }
}

然后你可以像这样在 .NET 5+ 中使用JsonSerializer

using System.Text.Json;
...
var res = JsonSerializer.Deserialize<Response>(sourceText);

Newtonsoft.Json 像这样:

using Newtonsoft.Json;
...
var res2 = JsonConvert.DeserializeObject<Response>(sourceText);

【讨论】:

  • 这不是我的问题的解决方案;没有这些属性我就无法工作。
【解决方案2】:

看到没有“开箱即用”选项并使用 Martin Simecek 方法。 决定将记录数组转换为string[][]类型并创建如下方法。

    /// <summary>
    /// Returns the record array as an object of type T
    /// </summary>
    public T[] RecordsAsEntity()
    {
        /* The result array of generic type T */
        var result = new T[Records.Length];
        
        /*
         * The field array specifies the property name and order
         * of the records.
         * Iterate each record and using reflection create a new
         * instance and populate the respective property with the
         * value.
         * We need to unsure that: fields.length == records[].length
         */
        var type = typeof(T);
        for (int i = 0; i < Records.Length; i++)
        {
            var record = Records[i];

            /* Create a new T instance */
            var obj = (T)Activator.CreateInstance(type);

            /* Iterate the columns */
            for (int j = 0; j < Fields.Length; j++)
            {
                var propertyName = Fields[j];

                /* Set the value of the repective property */
                var prop = type.GetProperty(propertyName);
                prop.SetValue(obj, record[j]);

            }

            /* Save the created instance in the result array */
            result[i] = obj;
        }

        return result;
    }

前面的方法不包括几个验证规则。注意这个方法只支持字符串属性,相信属性名一直存在。

【讨论】:

  • 尽管这种方法可能有效,但它很容易出错。如果Fields 包含不相关属性的名称怎么办?您很可能会收到NullReferenceException
  • @PeterCsala 我没有包括所有验证,因为它是在我服务的另一部分进行的。但我会在答案中提到它谢谢!
猜你喜欢
  • 2020-01-06
  • 1970-01-01
  • 1970-01-01
  • 2018-12-02
  • 1970-01-01
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多