【问题标题】:How to add properties at runtime to JSON (C#)如何在运行时将属性添加到 JSON (C#)
【发布时间】:2020-05-29 13:36:22
【问题描述】:

注意:我正在使用 System.Text.Json 包 下面是我从数据库中获取的 JSON。我必须遍历 JSON 中的每个键并检查键名中是否有句点(.);如果是这样,我需要在 JSON 中添加一个值为true 的属性required,以便提供运行时验证:

validate:{"required", true}

这是我的 JSON:

{
    "display": "wizard",
    "settings": {},
    "components": [{
        "title": "Event Information",
        "label": "Event Information",
        "type": "panel",
        "key": "EventInformation",
        "components": [{
            "label": "Row1Columns",
            "columns": [{
                "components": [{
                    "label": "Event Date",
                    "format": "dd/MM/yyyy hh:mm a",
                    "tableView": false,
                    "datePicker": {
                        "disableWeekends": false,
                        "disableWeekdays": false
                    },
                    "validate": {
                        "unique": true
                    },
                    "key": "Event.EventDate",
                    "type": "datetime",
                    "input": true,
                    "suffix": "<i ref=\"icon\" class=\"fa fa-calendar\" style=\"\"></i>",
                    "widget": {
                        "type": "calendar",
                        "displayInTimezone": "viewer",
                        "language": "en",
                        "useLocaleSettings": false,
                        "allowInput": true,
                        "mode": "single",
                        "enableTime": true,
                        "noCalendar": false,
                        "format": "dd/MM/yyyy hh:mm a",
                        "hourIncrement": 1,
                        "minuteIncrement": 1,
                        "time_24hr": false,
                        "minDate": null,
                        "disableWeekends": false,
                        "disableWeekdays": false,
                        "maxDate": null
                    }
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }, {
                "components": [{
                    "label": "Duration (minutes)",
                    "mask": false,
                    "spellcheck": true,
                    "tableView": false,
                    "delimiter": false,
                    "requireDecimal": false,
                    "inputFormat": "plain",
                    "key": "Event.Duration",
                    "type": "number",
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }],
            "tableView": false,
            "key": "row1Columns",
            "type": "columns",
            "input": false
        }, {
            "label": "Row2Columns",
            "columns": [{
                "components": [{
                    "label": "Event Category",
                    "widget": "choicesjs",
                    "tableView": true,
                    "dataSrc": "custom",
                    "data": {
                        "custom": "values = getEventCategoryValues()"
                    },
                    "valueProperty": "AgencyEventCategoryId",
                    "template": "<span>{{ item.text }}</span>",
                    "selectThreshold": 0.3,
                    "validate": {
                        "required": true
                    },
                    "key": "Event.AgencyEventCategoryId",
                    "type": "select",
                    "indexeddb": {
                        "filter": {}
                    },
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }, {
                "components": [{
                    "label": "Attendance",
                    "widget": "choicesjs",
                    "tableView": true,
                    "multiple": false,
                    "dataSrc": "custom",
                    "data": {
                        "custom": "values = getAttendanceValues()"
                    },
                    "valueProperty": "AgencyEventAttendanceId",
                    "template": "<span>{{ item.text }}</span>",
                    "selectThreshold": 0.3,
                    "validate": {
                        "required": true,
                    },
                    "key": "Event.AgencyEventAttendanceId",
                    "type": "select",
                    "indexeddb": {
                        "filter": {}
                    },
                    "input": true
                }],
                "width": 6,
                "offset": 0,
                "push": 0,
                "pull": 0
            }],
            "tableView": false,
            "key": "row2Columns",
            "type": "columns",
            "input": false
        }, {
            "label": "Event Options",
            "widget": "choicesjs",
            "tableView": true,
            "multiple": true,
            "dataSrc": "custom",
            "data": {
                "custom": "values = getEventManagerValues(data.Event.AgencyEventCategoryId)"
            },
            "template": "<span>{{ item.text }}</span>",
            "refreshOn": "Event.AgencyEventCategoryId",
            "clearOnRefresh": true,
            "selectThreshold": 0.3,
            "calculateServer": false,
            "validate": {
                "required": true,
                "multiple": true
            },
            "key": "Event.EventDetail",
            "type": "select",
            "indexeddb": {
                "filter": {}
            },
            "input": true
        }, {
            "label": "Casenote",
            "wysiwyg": true,
            "autoExpand": true,
            "spellcheck": true,
            "tableView": true,
            "calculateServer": false,
            "key": "Event.EventCasenote[0].Casenote",
            "type": "textarea",
            "input": true
        }],
        "input": false,
        "tableView": false,
        "breadcrumbClickable": true,
        "buttonSettings": {
            "previous": true,
            "cancel": true,
            "next": true
        },
        "collapsible": false
    }]
} 

【问题讨论】:

    标签: c# json asp.net-mvc json.net runtime


    【解决方案1】:

    其中一个选项是将 json 解析为 JObject 并通过 Newtonsoft 的 Json.NET 向其添加属性:

    var obj = JObject.Parse("{'key':'value'}");
    obj.Add("required", true);
    Console.WriteLine(obj); // { "key": "value", "required": true }
    

    要添加新对象,您可以使用 Add 的重载:

    obj.Add("validate", JObject.FromObject(new { required = true }));
    

    所以整个解决方案将如下所示:

    var obj = JObect.Parse(your_json);
    
    foreach(var token in obj.DescendantsAndSelf().ToList()) // ToList is important!!!
    {
        if(token is JObject xObj)
        {
            // check your conditions for adding property
            // check if object does not have "validate" property
            if(satisfies_all_conditions)
            {
                xObj.Add("validate", JObject.FromObject(new { required = true }));
            }
        }
    }
    

    【讨论】:

    • 我在事件日期中对我的 json 进行了更改,我删除了必需的属性,并且从持续时间我删除了完整的验证对象,并且通过使用您的解决方案,我没有为这两个对象添加必填字段。你能详细说明一下吗,因为我是新手,你能给我 SYSTEM.JSON.TEXT pkg 的解决方案吗
    【解决方案2】:

    我有similar issue,并找到了解决方案,请参见下面的代码和 cmets。虽然我正在使用Newtonsoft,但值得检查您是否可以使用Newtonsoft 库并且还没有找到System.Text.Json 的解决方案。

    您的JSON 中的所有控件都是组件对象/数组的一部分,因此我们可以使用JSONPath,更多信息请参见链接details。

    public void IterateJson(JObject obj, string mandatoryFieldKey)
            {
    JToken jTokenFoundForMandatoryField = obj.SelectToken
    ("$..components[?(@.key == '" + mandatoryFieldKey + "')]");   
                //Now we convert this oken into an object so that we can add properties/objects in it
                if (jTokenFoundForMandatoryField is JObject jObjectForMandatoryField)
                {
                    //We check if validate already exists for this field, if it does not
     //exists then we add validate and required property inside the if condition
                    if (jObjectForMandatoryField["validate"] == null)
                        jObjectForMandatoryField.Add("validate", 
    JObject.FromObject(new { required = true })); //add validate and required property
                    else
                    {
                        //If validate does not exists then code comes here and 
    //we convert the validate into a JObject using is JObject statement
                        if (jObjectForMandatoryField["validate"] is JObject validateObject)
                        {
                            //We need to check if required property already exists, 
    //if it does not exists then we add it inside the if condition.
                            if (validateObject["required"] == null)
                            {
                                validateObject.Add("required", true); //add required property
                            }
                        }
                    }                
                }  
    }   
    

    【讨论】:

      【解决方案3】:

      这对我来说很有趣,所以这是我写的

      class Program
      {
          static void Main(string[] args)
          {
              string jsonFilePath = @"test.json"; //path to your json
              string json = File.ReadAllText(jsonFilePath);
              var data = JObject.Parse(json);
              CheckJson(data);
              Console.ReadLine();
          }
      
          static void CheckJson(JToken value)
          {
              if (value.Values().Count() != 0) //if more than 0 - so value is object or array and we have to call this method for each property
              {
                  foreach (var item in value.Values().ToList())
                  {
                      CheckJson(item);
                  }
              }
              else if (true) //else - we have exactly value of key, which we can check, for example if . exists or additional checks
              {
                  if (value.Parent.Parent is JObject jObject && jObject["validate"] == null) //check if above "required" property exists 
                  {
                      jObject.Add("validate", JObject.FromObject(new { required = true })); //add required property
                  }
              }
      
          }
      }
      

      如果不存在,此代码将在每个对象属性中添加“必需”。 所有你需要的 - 只需添加验证方法并在 if 块中调用它。 最好添加额外的验证,如果“必需”属性存在,则不会继续检查所有属性

      【讨论】:

      • 我在事件日期中对我的 json 进行了更改,我删除了必需的属性,并且从持续时间我删除了完整的验证对象,并且通过使用您的解决方案,我没有为这两个对象添加必填字段。你能详细说明一下吗,因为我是新手,你能给我 SYSTEM.JSON.TEXT pkg 的解决方案吗
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      • 2021-08-27
      • 2020-10-28
      相关资源
      最近更新 更多