1

我有以下 JSON 用于定义表单,但每个“部分”(例如培训、教育)不在数组中。

我需要将每个顶部部分(例如培训等)转换为 C#Section类,以及该 a 下的字段List<Field>等,以便随后可以呈现它。

这是我正在使用的 JSON。我尝试了各种反序列化方法,但都没有奏效。

{
  "readonly": "True",

  "Training": {
    "entity": "PNLCAND",
    "type": "standard",
    "mode": "update",
    "fields": {
      "HEADER_3": {
        "caption": "Please enter all relevant work related courses",
        "type": "header",
        "update": "",
        "mandatory": false,
        "tooltip": ""
      },
      "HEADER_5": {
        "caption": "",
        "type": "header",
        "update": "",
        "mandatory": false,
        "tooltip": ""
      },
      "HEADER_6": {
        "caption": "",
        "type": "header",
        "update": "",
        "mandatory": false,
        "tooltip": ""
      }

    }
  },
  "Education": {
    "entity": "PNLCANQUA",
    "type": "repeating",
    "mode": "update",
    "fields": {
      "Q_SUBJECT": {
        "caption": "Qualifications gained",
        "type": "string",
        "length": 40,
        "update": "Y",
        "mandatory": false,
        "tooltip": ""
      },
      "TO_DATE": {
        "caption": "Date Awarded/Expected",
        "type": "date",
        "range": {
          "start": -60,
          "end": 0
        },
        "update": "Y",
        "mandatory": false,
        "tooltip": ""
      },
      "Q_GRADE": {
        "caption": "Grade/Level",
        "type": "string",
        "length": 40,
        "update": "Y",
        "mandatory": false,
        "tooltip": ""
      },
      "Q_LOCATION": {
        "caption": "School / Colleges, Universities or Institutes of Further Education",
        "type": "string",
        "length": 40,
        "update": "Y",
        "mandatory": false,
        "tooltip": ""
      }
    },
    "values": [
      {
        "TO_DATE": "2019-08-01",
        "Q_SUBJECT": "Qual 1",
        "Q_LOCATION": "School",
        "Q_GRADE": "a",
        "UDF_6_EDU001": "C"
      },
      {
        "TO_DATE": "2019-08-01",
        "Q_SUBJECT": "Qual 2",
        "Q_LOCATION": "School",
        "Q_GRADE": "a",
        "UDF_6_EDU001": "C"
      },
      {
        "TO_DATE": "2019-08-31",
        "Q_SUBJECT": "Qual 3",
        "Q_LOCATION": "Uni",
        "UDF_6_EDU001": "U"
      }
    ]
  },

}
4

2 回答 2

1

JsonConverter如果要将顶级部分和其中的可变名称字段反序列化为列表,则需要使用自定义。可以以通用方式编写转换器,以同时处理部分和字段。

首先我们需要定义一个模型来捕获数据:

public class Section
{
    public string Name { get; set; }
    public string Entity { get; set; }
    public string Type { get; set; }
    public string Mode { get; set; }
    public List<Field> Fields { get; set; }
    public List<Dictionary<string, string>> Values { get; set; }
}

public class Field
{
    public string Name { get; set; }
    public string Caption { get; set; }
    public string Type { get; set; }
    public Range Range { get; set; }
    public int Length { get; set; }
    public string Update { get; set; }
    public bool Mandatory { get; set; }
}

public class Range
{
    public int Start { get; set; }
    public int End { get; set; }
}

这是一个通用的JsonConverter,它将处理创建列表。类的T通用参数指定用于列表的项目类型(例如SectionField)。构造keyPropertyName函数参数告诉转换器应该使用模型上的哪个属性来存储来自 JSON 的项目的密钥。我为此添加了Name属性Section,因此在这两种情况下都应该传递。Field"Name"

转换器通过将 JSON 加载到 aJObject并迭代其属性来工作,不包括其值不是对象的任何属性(因此这将跳过顶层的“只读”属性,这显然不是一个部分)。使用该ToObject<T>方法将剩余的属性值转换为模型对象(首先在其上设置名称之后)并添加到返回列表中。

public class ObjectToListConverter<T> : JsonConverter
{
    public string KeyPropertyName { get; set; }

    public ObjectToListConverter(string keyPropertyName)
    {
        KeyPropertyName = keyPropertyName;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<T>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        List<T> list = new List<T>();
        foreach (JProperty prop in obj.Properties().Where(p => p.Value.Type == JTokenType.Object))
        {
            JToken item = prop.Value;
            item[KeyPropertyName] = prop.Name;
            list.Add(item.ToObject<T>(serializer));
        }
        return list;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用此转换器,请为两者传递一个实例,SectionField喜欢JsonConvert.DeserializeObject这样:

List<Section> sections = JsonConvert.DeserializeObject<List<Section>>(json, 
    new ObjectToListConverter<Section>("Name"), new ObjectToListConverter<Field>("Name"));

这是一个工作演示:https ://dotnetfiddle.net/A4uAGk

于 2019-09-09T06:02:58.100 回答
0

您必须创建一个 Training 类,它看起来与您的 json 结构完全相同。然后使用 dapper/automapper 绑定截面模型对象。

于 2019-09-04T12:13:49.923 回答