如何以 html 形式表示 json 数组
How do you represent a json array in an html form
注意:我也在使用 AspNetBoilerplate's template and Mecons 标签助手,所以 bc-
属性和 form-group
标签是有效的。
我正在尝试 post 我的一项应用程序服务的模型。但是我收到以下错误
"The following errors were detected during validation.
↵ - Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1[App.Stores.StoreWalk.Dtos.CreateOrEditStoreWalkCategoryDto]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
↵To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
↵Path 'categories.0', line 1, position 84.
↵"message: "Your request is not valid!"validationErrors: [{…}]proto: Object
我明白错误的含义,只是不知道如何修复我的代码。
在 2 条建议中,To fix this error either change the JSON to a JSON array (e.g. [1,2,3])
是我必须走的路。
可能无关紧要,但我在玩我的代码时注意到,当我从我的 name
属性中删除 @i
和 @j
时,我能够 post 成功,但是我的单选按钮失去了所有功能(由于命名冲突,单击第二行更改第一行),而且,我认为需要索引来保持它们的唯一性(我还在学习,如果我错了请纠正我)。
我 post 返回的 json 字符串是通过调用 $('form[name=StoreWalkForm]').serializeFormToObject()
创建的,如下所示并利用 https://github.com/marioizquierdo/jquery.serializeJSON
$.fn.serializeFormToObject = function() {
var $form = $(this);
var fields = $form.find('[disabled]');
fields.prop('disabled', false);
var json = $form.serializeJSON();
fields.prop('disabled', true);
return json;
};
JSON
{
"version": "2",
"department": {
"id": "8",
"name": "ISF"
},
"store": "001",
"categories": {
"0": {
"category": {
"id": "4"
},
"questions": {
"0": {
"question": {
"question": "SIGNAGE",
"id": "233"
},
"answer": {
"boolValue": "false",
"comments": "1"
}
},
"1": {
"question": {
"question": "PARKING LOT BLACKTOP",
"id": "234"
},
"answer": {
"boolValue": "true",
"comments": "2"
}
}
}
}
},
"comments": "123",
"signature": ""
}
型号Class
public class CreateOrEditStoreWalkDto : EntityDto<int?>
{
[Required]
public string Store { get; set; }
public string Comments { get; set; }
public byte[] Signature { get; set; }
public int Version { get; set; }
public DepartmentsDto Department { get; set; }
public IList<CreateOrEditStoreWalkCategoryDto> Categories { get; set; } = new List<CreateOrEditStoreWalkCategoryDto>();
}
public class CreateOrEditStoreWalkCategoryDto
{
public CategoriesDto Category { get; set; }
public IList<CreateOrEditStoreWalkQuestionDto> Questions { get; set; } = new List<CreateOrEditStoreWalkQuestionDto>();
}
public class CreateOrEditStoreWalkQuestionDto
{
public QuestionsDto Question { get; set; }
public AnswersDto Answer { get; set; }
}
CSHHTML
<form name="StoreWalkInformationsForm" role="form" enctype="multipart/form-data" novalidate class="form-validation">
@if (Model.IsEditMode)
{
<input type="hidden" name="id" value="@Model.StoreWalk.Id" />
}
<input type="hidden" name="version" value="@Model.StoreWalk.Version" />
<input type="hidden" name="department[id]" value="@Model.StoreWalk.Department.Id" />
<input type="hidden" name="department[name]" value="@Model.StoreWalk.Department.Name" />
<form-group>
<select id="StoreWalk_Store" name="store" bc-label="@L("Store")" required="required" bc-required="true" bc-validation="true" value="@Model.StoreWalk.Store" maxlength="@App.Stores.StoreWalk.EntriesConsts.MaxStoreLength" minlength="@App.Stores.StoreWalk.EntriesConsts.MinStoreLength">
@if (!Model.IsEditMode)
{
<option value="" selected="selected"></option>
}
</select>
</form-group>
<br /><br />
@for (var i = 0; i < Model.StoreWalk.Categories.Count; i++)
{
<h5 class="m--font-primary">@Model.StoreWalk.Categories[i].Category.Name</h5>
<input type="hidden" name="categories[@i][category][id]" value="@Model.StoreWalk.Categories[i].Category.Id" />
<table bc-responsive="true">
<thead>
<tr>
<th>#</th>
<th scope="col">Question</th>
<th scope="col"></th>
<th scope="col">Comments</th>
</tr>
</thead>
<tbody>
@*@for (var j = 0; j < Model.StoreWalk.Categories[i].Questions.Count; j++)*@
@for (var j = 0; j < 2; j++)
{
<tr>
<td>@(q.Next()).</td>
<td scope="row">
<form-group>
<input type="hidden" name="categories[@i][questions][@j][question][question]" value="@Model.StoreWalk.Categories[i].Questions[j].Question.Question" bc-label="@Model.StoreWalk.Categories[i].Questions[j].Question.Question" />
<input type="hidden" name="categories[@i][questions][@j][question][id]" value="@Model.StoreWalk.Categories[i].Questions[j].Question.Id" />
<br />
@Html.TextBoxFor(m => m.StoreWalk.Categories[i].Questions[j].S3Files, new { type = "file", multiple = "multiple" })
</form-group>
</td>
<td>
<form-group>
<radio-list bc-required="true" bc-validation="true" id="categories[@i][questions][@j][answer][boolValue]">
<input type="radio" name="categories[@i][questions][@j][answer][boolValue]" value="true" bc-label="@L("Yes")" required="required" />
<input type="radio" name="categories[@i][questions][@j][answer][boolValue]" value="false" bc-label="@L("No")" required="required" />
</radio-list>
</form-group>
</td>
<td>
<form-group>
<textarea name="categories[@i][questions][@j][answer][comments]" rows="3">@Model.StoreWalk.Categories[i].Questions[j].Answer.Comments</textarea>
</form-group>
</td>
</tr>
}
</tbody>
</table>
}
<form-group>
<textarea class="form-control" id="StoreWalk_Comments" type="text" name="comments" bc-label="@L("Comments")" rows="4">@Model.StoreWalk.Comments</textarea>
</form-group>
<form-group>
<label for="signature">@L("Signature")</label>
@Html.Partial("~/Areas/Shared/Views/Shared/SignaturePad/Edit.cshtml", new SignaturePadModel()
{
Id = "signature",
Data = Model.StoreWalk.Signature,
FooterText = L("Signature"),
Required = true
})
</form-group>
</form>
将 {useIntKeysAsArrayIndex: true}
传递给 $form.serializeJSON()
。
$.fn.serializeFormToObject = function() {
var $form = $(this);
var fields = $form.find('[disabled]');
fields.prop('disabled', false);
// var json = $form.serializeJSON();
var json = $form.serializeJSON({useIntKeysAsArrayIndex: true});
fields.prop('disabled', true);
return json;
};
来自问题中链接的 https://github.com/marioizquierdo/jquery.serializeJSON:
Use integer keys as array indexes
<form>
<input type="text" name="arr[0]" value="foo"/>
<input type="text" name="arr[1]" value="var"/>
<input type="text" name="arr[5]" value="inn"/>
</form>
$('form').serializeJSON();
// arr is an object =>
{'arr': {'0': 'foo', '1': 'var', '5': 'inn' }}
$('form').serializeJSON({useIntKeysAsArrayIndex: true});
// arr is an array =>
{'arr': ['foo', 'var', undefined, undefined, undefined, 'inn']}
注意:我也在使用 AspNetBoilerplate's template and Mecons 标签助手,所以 bc-
属性和 form-group
标签是有效的。
我正在尝试 post 我的一项应用程序服务的模型。但是我收到以下错误
"The following errors were detected during validation. ↵ - Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1[App.Stores.StoreWalk.Dtos.CreateOrEditStoreWalkCategoryDto]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. ↵To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. ↵Path 'categories.0', line 1, position 84. ↵"message: "Your request is not valid!"validationErrors: [{…}]proto: Object
我明白错误的含义,只是不知道如何修复我的代码。
在 2 条建议中,To fix this error either change the JSON to a JSON array (e.g. [1,2,3])
是我必须走的路。
可能无关紧要,但我在玩我的代码时注意到,当我从我的 name
属性中删除 @i
和 @j
时,我能够 post 成功,但是我的单选按钮失去了所有功能(由于命名冲突,单击第二行更改第一行),而且,我认为需要索引来保持它们的唯一性(我还在学习,如果我错了请纠正我)。
我 post 返回的 json 字符串是通过调用 $('form[name=StoreWalkForm]').serializeFormToObject()
创建的,如下所示并利用 https://github.com/marioizquierdo/jquery.serializeJSON
$.fn.serializeFormToObject = function() {
var $form = $(this);
var fields = $form.find('[disabled]');
fields.prop('disabled', false);
var json = $form.serializeJSON();
fields.prop('disabled', true);
return json;
};
JSON
{
"version": "2",
"department": {
"id": "8",
"name": "ISF"
},
"store": "001",
"categories": {
"0": {
"category": {
"id": "4"
},
"questions": {
"0": {
"question": {
"question": "SIGNAGE",
"id": "233"
},
"answer": {
"boolValue": "false",
"comments": "1"
}
},
"1": {
"question": {
"question": "PARKING LOT BLACKTOP",
"id": "234"
},
"answer": {
"boolValue": "true",
"comments": "2"
}
}
}
}
},
"comments": "123",
"signature": ""
}
型号Class
public class CreateOrEditStoreWalkDto : EntityDto<int?>
{
[Required]
public string Store { get; set; }
public string Comments { get; set; }
public byte[] Signature { get; set; }
public int Version { get; set; }
public DepartmentsDto Department { get; set; }
public IList<CreateOrEditStoreWalkCategoryDto> Categories { get; set; } = new List<CreateOrEditStoreWalkCategoryDto>();
}
public class CreateOrEditStoreWalkCategoryDto
{
public CategoriesDto Category { get; set; }
public IList<CreateOrEditStoreWalkQuestionDto> Questions { get; set; } = new List<CreateOrEditStoreWalkQuestionDto>();
}
public class CreateOrEditStoreWalkQuestionDto
{
public QuestionsDto Question { get; set; }
public AnswersDto Answer { get; set; }
}
CSHHTML
<form name="StoreWalkInformationsForm" role="form" enctype="multipart/form-data" novalidate class="form-validation">
@if (Model.IsEditMode)
{
<input type="hidden" name="id" value="@Model.StoreWalk.Id" />
}
<input type="hidden" name="version" value="@Model.StoreWalk.Version" />
<input type="hidden" name="department[id]" value="@Model.StoreWalk.Department.Id" />
<input type="hidden" name="department[name]" value="@Model.StoreWalk.Department.Name" />
<form-group>
<select id="StoreWalk_Store" name="store" bc-label="@L("Store")" required="required" bc-required="true" bc-validation="true" value="@Model.StoreWalk.Store" maxlength="@App.Stores.StoreWalk.EntriesConsts.MaxStoreLength" minlength="@App.Stores.StoreWalk.EntriesConsts.MinStoreLength">
@if (!Model.IsEditMode)
{
<option value="" selected="selected"></option>
}
</select>
</form-group>
<br /><br />
@for (var i = 0; i < Model.StoreWalk.Categories.Count; i++)
{
<h5 class="m--font-primary">@Model.StoreWalk.Categories[i].Category.Name</h5>
<input type="hidden" name="categories[@i][category][id]" value="@Model.StoreWalk.Categories[i].Category.Id" />
<table bc-responsive="true">
<thead>
<tr>
<th>#</th>
<th scope="col">Question</th>
<th scope="col"></th>
<th scope="col">Comments</th>
</tr>
</thead>
<tbody>
@*@for (var j = 0; j < Model.StoreWalk.Categories[i].Questions.Count; j++)*@
@for (var j = 0; j < 2; j++)
{
<tr>
<td>@(q.Next()).</td>
<td scope="row">
<form-group>
<input type="hidden" name="categories[@i][questions][@j][question][question]" value="@Model.StoreWalk.Categories[i].Questions[j].Question.Question" bc-label="@Model.StoreWalk.Categories[i].Questions[j].Question.Question" />
<input type="hidden" name="categories[@i][questions][@j][question][id]" value="@Model.StoreWalk.Categories[i].Questions[j].Question.Id" />
<br />
@Html.TextBoxFor(m => m.StoreWalk.Categories[i].Questions[j].S3Files, new { type = "file", multiple = "multiple" })
</form-group>
</td>
<td>
<form-group>
<radio-list bc-required="true" bc-validation="true" id="categories[@i][questions][@j][answer][boolValue]">
<input type="radio" name="categories[@i][questions][@j][answer][boolValue]" value="true" bc-label="@L("Yes")" required="required" />
<input type="radio" name="categories[@i][questions][@j][answer][boolValue]" value="false" bc-label="@L("No")" required="required" />
</radio-list>
</form-group>
</td>
<td>
<form-group>
<textarea name="categories[@i][questions][@j][answer][comments]" rows="3">@Model.StoreWalk.Categories[i].Questions[j].Answer.Comments</textarea>
</form-group>
</td>
</tr>
}
</tbody>
</table>
}
<form-group>
<textarea class="form-control" id="StoreWalk_Comments" type="text" name="comments" bc-label="@L("Comments")" rows="4">@Model.StoreWalk.Comments</textarea>
</form-group>
<form-group>
<label for="signature">@L("Signature")</label>
@Html.Partial("~/Areas/Shared/Views/Shared/SignaturePad/Edit.cshtml", new SignaturePadModel()
{
Id = "signature",
Data = Model.StoreWalk.Signature,
FooterText = L("Signature"),
Required = true
})
</form-group>
</form>
将 {useIntKeysAsArrayIndex: true}
传递给 $form.serializeJSON()
。
$.fn.serializeFormToObject = function() {
var $form = $(this);
var fields = $form.find('[disabled]');
fields.prop('disabled', false);
// var json = $form.serializeJSON();
var json = $form.serializeJSON({useIntKeysAsArrayIndex: true});
fields.prop('disabled', true);
return json;
};
来自问题中链接的 https://github.com/marioizquierdo/jquery.serializeJSON:
Use integer keys as array indexes
<form> <input type="text" name="arr[0]" value="foo"/> <input type="text" name="arr[1]" value="var"/> <input type="text" name="arr[5]" value="inn"/> </form>
$('form').serializeJSON(); // arr is an object => {'arr': {'0': 'foo', '1': 'var', '5': 'inn' }}
$('form').serializeJSON({useIntKeysAsArrayIndex: true}); // arr is an array => {'arr': ['foo', 'var', undefined, undefined, undefined, 'inn']}