使用 Newtonsoft.Json 将 属性 添加到 json 的指定位置
Adding a property into specified location into json using Newtonsoft.Json
我有一个追随者JSON
。我添加了 2 个双引号 ,这样我就可以在 c#
中将其声明为 string
变量,实际上它包含属性的一次双引号。
完整的示例代码在 fiddle.
我正在使用 Newtonsoft
,但也可以使用 System.Text.Json
,因此我们将不胜感激。
{
""display"": ""wizard"",
""settings"": {},
""components"": [
{
""title"": ""Activity Information"",
""label"": ""Activity Information"",
""type"": ""Activity"",
""key"": ""ActivityInformation"",
""components"": [
{
""label"": ""Row1Columns"",
""columns"": [
{
""components"": [
{
""label"": ""Activity Date"",
""format"": ""dd/MM/yyyy hh:mm a"",
""tableView"": false,
""datePicker"": {
""disableWeekends"": false,
""disableWeekdays"": false
},
""validate"": {
""unique"": true
},
""key"": ""Activity.ActivityDate"",
""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"": ""Activity.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"": ""Activity Category"",
""widget"": ""choicesjs"",
""tableView"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityCategoryValues()""
},
""valueProperty"": ""AgencyActivityCategoryId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""validate"": {
""required"": true
},
""key"": ""Activity.AgencyActivityCategoryId"",
""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"": ""AgencyActivityAttendanceId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""key"": ""Activity.AgencyActivityAttendanceId"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""width"": 6,
""offset"": 0,
""push"": 0,
""pull"": 0
}
],
""tableView"": false,
""key"": ""row2Columns"",
""type"": ""columns"",
""input"": false
},
{
""label"": ""Activity Options"",
""widget"": ""choicesjs"",
""tableView"": true,
""multiple"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityManagerValues(data.Activity.AgencyActivityCategoryId)""
},
""template"": ""<span>{{ item.text }}</span>"",
""refreshOn"": ""Activity.AgencyActivityCategoryId"",
""clearOnRefresh"": true,
""selectThreshold"": 0.3,
""calculateServer"": false,
""validate"": {
""required"": true,
""multiple"": true
},
""key"": ""Activity.ActivityDetail"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""input"": false,
""tableView"": false,
""breadcrumbClickable"": true,
""buttonSettings"": {
""previous"": true,
""cancel"": true,
""next"": true
},
""collapsible"": false
}
]
}
我想添加验证,如果我的 JSON
的键与我列表中的项目匹配,则需要它的子键。
我有三种情况,它们根据下面代码中的注释进行了解释。
public static void Main()
{
Console.WriteLine("BEFORE MANDATORY");
List<string> mandatoryKeys = new List<string>();
//Scenario 1: Has validate key but not required key in json, so we need to add "required": true
//inside existing "validate"
mandatoryKeys.Add("Activity.ActivityDate");
//Scenario 2: Does not have both validate and required so will need to have both "validate" and its child "required"
mandatoryKeys.Add("Activity.Duration");
//Scenario 3: Has both "validate" and "required" so we should not add it again
mandatoryKeys.Add("Activity.AgencyActivityCategoryId");
//Scenario 2 again for double checking
mandatoryKeys.Add("Activity.AgencyActivityAttendanceId");
var data = JObject.Parse(GetRawJson());
Console.WriteLine(data);
for(int i = 0; i < mandatoryKeys.Count(); i++)
IterateJson(data, mandatoryKeys[i]);
Console.WriteLine("AFTER MANDATORY");
Console.WriteLine("XXXXXXXXXXXXXXX");
Console.WriteLine(data);
Console.ReadLine();
}
下面显示JSON
迭代函数。
static void IterateJson(JToken value, string mandatoryFieldKey)
{
//if more than 0 - so value is object or array and we have to call this method for each property
if (value.Values().Count() != 0)
{
foreach (var item in value.Values().ToList())
{
IterateJson(item, mandatoryFieldKey);
}
}
else if (value.ToString() == mandatoryFieldKey)
{
Console.WriteLine("HELLO");
//check if above "required" property exists
if (value.Parent.Parent is JObject jObject && jObject["validate"] == null)
{
Console.WriteLine(value);
jObject.Add("validate", JObject.FromObject(new { required = true })); //add required property
}
}
}
我的最终 JSON
应该如下所示。
{
""display"": ""wizard"",
""settings"": {},
""components"": [
{
""title"": ""Activity Information"",
""label"": ""Event Information"",
""type"": ""Activity"",
""key"": ""ActivityInformation"",
""components"": [
{
""label"": ""Row1Columns"",
""columns"": [
{
""components"": [
{
""label"": ""Activity Date"",
""format"": ""dd/MM/yyyy hh:mm a"",
""tableView"": false,
""datePicker"": {
""disableWeekends"": false,
""disableWeekdays"": false
},
""validate"": {
""required"": true,
""unique"": true
},
""key"": ""Activity.ActivityDate"",
""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"",
""validate"": {
""required"": true
},
""key"": ""Activity.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"": ""Activity Category"",
""widget"": ""choicesjs"",
""tableView"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityCategoryValues()""
},
""valueProperty"": ""AgencyActivityCategoryId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""validate"": {
""required"": true
},
""key"": ""Activity.AgencyActivityCategoryId"",
""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"": ""AgencyActivityAttendanceId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""validate"": {
""required"": true
},
""key"": ""Activity.AgencyActivityAttendanceId"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""width"": 6,
""offset"": 0,
""push"": 0,
""pull"": 0
}
],
""tableView"": false,
""key"": ""row2Columns"",
""type"": ""columns"",
""input"": false
},
{
""label"": ""Activity Options"",
""widget"": ""choicesjs"",
""tableView"": true,
""multiple"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityManagerValues(data.Activity.AgencyActivityCategoryId)""
},
""template"": ""<span>{{ item.text }}</span>"",
""refreshOn"": ""Activity.AgencyActivityCategoryId"",
""clearOnRefresh"": true,
""selectThreshold"": 0.3,
""calculateServer"": false,
""validate"": {
""required"": true,
""multiple"": true
},
""key"": ""Activity.ActivityDetail"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""input"": false,
""tableView"": false,
""breadcrumbClickable"": true,
""buttonSettings"": {
""previous"": true,
""cancel"": true,
""next"": true
},
""collapsible"": false
}
]
}
我无法实现所有三种方案。有人可以看看并提供解决方案吗?此外,如果有更好的方法来完成此操作,请提供该方法的解决方案。
我创建了一个 fiddle 以便于帮助我。
我已经设法解决了这个问题,在这里发布了一个解决方案,以防它能帮助到其他人。我已经意识到 json 中的所有控件都是组件 object/array 的一部分,因此我们可以使用 JSONPath
,请参阅 link 了解更多 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
}
}
}
}
}
我有一个追随者JSON
。我添加了 2 个双引号 ,这样我就可以在 c#
中将其声明为 string
变量,实际上它包含属性的一次双引号。
完整的示例代码在 fiddle.
我正在使用 Newtonsoft
,但也可以使用 System.Text.Json
,因此我们将不胜感激。
{
""display"": ""wizard"",
""settings"": {},
""components"": [
{
""title"": ""Activity Information"",
""label"": ""Activity Information"",
""type"": ""Activity"",
""key"": ""ActivityInformation"",
""components"": [
{
""label"": ""Row1Columns"",
""columns"": [
{
""components"": [
{
""label"": ""Activity Date"",
""format"": ""dd/MM/yyyy hh:mm a"",
""tableView"": false,
""datePicker"": {
""disableWeekends"": false,
""disableWeekdays"": false
},
""validate"": {
""unique"": true
},
""key"": ""Activity.ActivityDate"",
""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"": ""Activity.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"": ""Activity Category"",
""widget"": ""choicesjs"",
""tableView"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityCategoryValues()""
},
""valueProperty"": ""AgencyActivityCategoryId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""validate"": {
""required"": true
},
""key"": ""Activity.AgencyActivityCategoryId"",
""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"": ""AgencyActivityAttendanceId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""key"": ""Activity.AgencyActivityAttendanceId"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""width"": 6,
""offset"": 0,
""push"": 0,
""pull"": 0
}
],
""tableView"": false,
""key"": ""row2Columns"",
""type"": ""columns"",
""input"": false
},
{
""label"": ""Activity Options"",
""widget"": ""choicesjs"",
""tableView"": true,
""multiple"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityManagerValues(data.Activity.AgencyActivityCategoryId)""
},
""template"": ""<span>{{ item.text }}</span>"",
""refreshOn"": ""Activity.AgencyActivityCategoryId"",
""clearOnRefresh"": true,
""selectThreshold"": 0.3,
""calculateServer"": false,
""validate"": {
""required"": true,
""multiple"": true
},
""key"": ""Activity.ActivityDetail"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""input"": false,
""tableView"": false,
""breadcrumbClickable"": true,
""buttonSettings"": {
""previous"": true,
""cancel"": true,
""next"": true
},
""collapsible"": false
}
]
}
我想添加验证,如果我的 JSON
的键与我列表中的项目匹配,则需要它的子键。
我有三种情况,它们根据下面代码中的注释进行了解释。
public static void Main()
{
Console.WriteLine("BEFORE MANDATORY");
List<string> mandatoryKeys = new List<string>();
//Scenario 1: Has validate key but not required key in json, so we need to add "required": true
//inside existing "validate"
mandatoryKeys.Add("Activity.ActivityDate");
//Scenario 2: Does not have both validate and required so will need to have both "validate" and its child "required"
mandatoryKeys.Add("Activity.Duration");
//Scenario 3: Has both "validate" and "required" so we should not add it again
mandatoryKeys.Add("Activity.AgencyActivityCategoryId");
//Scenario 2 again for double checking
mandatoryKeys.Add("Activity.AgencyActivityAttendanceId");
var data = JObject.Parse(GetRawJson());
Console.WriteLine(data);
for(int i = 0; i < mandatoryKeys.Count(); i++)
IterateJson(data, mandatoryKeys[i]);
Console.WriteLine("AFTER MANDATORY");
Console.WriteLine("XXXXXXXXXXXXXXX");
Console.WriteLine(data);
Console.ReadLine();
}
下面显示JSON
迭代函数。
static void IterateJson(JToken value, string mandatoryFieldKey)
{
//if more than 0 - so value is object or array and we have to call this method for each property
if (value.Values().Count() != 0)
{
foreach (var item in value.Values().ToList())
{
IterateJson(item, mandatoryFieldKey);
}
}
else if (value.ToString() == mandatoryFieldKey)
{
Console.WriteLine("HELLO");
//check if above "required" property exists
if (value.Parent.Parent is JObject jObject && jObject["validate"] == null)
{
Console.WriteLine(value);
jObject.Add("validate", JObject.FromObject(new { required = true })); //add required property
}
}
}
我的最终 JSON
应该如下所示。
{
""display"": ""wizard"",
""settings"": {},
""components"": [
{
""title"": ""Activity Information"",
""label"": ""Event Information"",
""type"": ""Activity"",
""key"": ""ActivityInformation"",
""components"": [
{
""label"": ""Row1Columns"",
""columns"": [
{
""components"": [
{
""label"": ""Activity Date"",
""format"": ""dd/MM/yyyy hh:mm a"",
""tableView"": false,
""datePicker"": {
""disableWeekends"": false,
""disableWeekdays"": false
},
""validate"": {
""required"": true,
""unique"": true
},
""key"": ""Activity.ActivityDate"",
""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"",
""validate"": {
""required"": true
},
""key"": ""Activity.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"": ""Activity Category"",
""widget"": ""choicesjs"",
""tableView"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityCategoryValues()""
},
""valueProperty"": ""AgencyActivityCategoryId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""validate"": {
""required"": true
},
""key"": ""Activity.AgencyActivityCategoryId"",
""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"": ""AgencyActivityAttendanceId"",
""template"": ""<span>{{ item.text }}</span>"",
""selectThreshold"": 0.3,
""validate"": {
""required"": true
},
""key"": ""Activity.AgencyActivityAttendanceId"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""width"": 6,
""offset"": 0,
""push"": 0,
""pull"": 0
}
],
""tableView"": false,
""key"": ""row2Columns"",
""type"": ""columns"",
""input"": false
},
{
""label"": ""Activity Options"",
""widget"": ""choicesjs"",
""tableView"": true,
""multiple"": true,
""dataSrc"": ""custom"",
""data"": {
""custom"": ""values = getActivityManagerValues(data.Activity.AgencyActivityCategoryId)""
},
""template"": ""<span>{{ item.text }}</span>"",
""refreshOn"": ""Activity.AgencyActivityCategoryId"",
""clearOnRefresh"": true,
""selectThreshold"": 0.3,
""calculateServer"": false,
""validate"": {
""required"": true,
""multiple"": true
},
""key"": ""Activity.ActivityDetail"",
""type"": ""select"",
""indexeddb"": {
""filter"": {}
},
""input"": true
}
],
""input"": false,
""tableView"": false,
""breadcrumbClickable"": true,
""buttonSettings"": {
""previous"": true,
""cancel"": true,
""next"": true
},
""collapsible"": false
}
]
}
我无法实现所有三种方案。有人可以看看并提供解决方案吗?此外,如果有更好的方法来完成此操作,请提供该方法的解决方案。
我创建了一个 fiddle 以便于帮助我。
我已经设法解决了这个问题,在这里发布了一个解决方案,以防它能帮助到其他人。我已经意识到 json 中的所有控件都是组件 object/array 的一部分,因此我们可以使用 JSONPath
,请参阅 link 了解更多 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
}
}
}
}
}