在 JSON 中何时使用包含对象的对象与对象数组的公认约定是什么?
What is the accepted convention for when to use an object containing objects vs an array of objects in JSON?
我目前正在编写一个 GUI,它基本上允许用户使用 AJAX edit/populate/delete 一些设置文件,这些设置存储在 JSON 中。
我对 JavaScript 的经验有限(坦率地说,我对 MATLAB 以外的任何东西都没有什么经验),但是由于处理包含更多对象的对象的语义,我发现自己正在重构我的设置结构,而不是一组对象。在 C# 中,我会使用 KeyValuePair 来执行此操作,但是 JSON 结构阻止我做我真正想在这里做的事情,我想知道在 JavaScript 我现在应该采用它,而不是进行这些更改并发现我造成的问题多于我解决的问题。
样本数据结构与我的许多结构具有相似的要求,它接受任意年数,在这些任意数量的事件中,在这些事件中接受一定数量的值。
这是之前的结构:
{"2013":
{
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...},
...}
这是我的理想结构,其中 year/event 名称作为数组类型值的字符串类型键:
["2013":
[
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...],
...]
据我所知,这将是无效的 JSON 表示法,所以这是我建议的结构:
[{"Key":"2013",
"Value":
[{"Key":"someEventName",
"Value":
{
"data1":"foo",
"data2":"bar",
...}
},
...]
},
...]
关于某物应该是包含对象的对象还是对象数组,我的建议"test"是"does my sub-structure take a fixed, known number of objects?"如果是,则设计为包含对象的对象;如果不是,设计成对象数组。
我需要经常过滤此结构以找到 data/values,并且我不打算利用使用数组带来的索引功能,但是从数组中推送和删除数据要多得多比对象更灵活,感觉使用包含对象的对象偏离了 OOP 的 class 模型;另一方面,如果它是一个包含对象的对象,通过 "Key" 查找我的数据的方法似乎都更简单,而且我不打算自己在这些对象上使用 Prototype 方法,所以谁关心破坏 OOP。
回复 1
例如,在前面的结构中添加年份,代码为 OBJ["2014"]={}
;在新结构中它将是 OBJ.push({"Key":"2014", "Value":{}})
;这两种解决方案都同样缺乏复杂性。
在这两种情况下删除同样微不足道。
但是,如果我想操纵事件的值,比如说,使用函数,如果我将指向该对象的指针传递给函数并尝试取代引用中的整个对象,它不会工作:我被迫复制原始事件(使用 jQuery 或更糟)并将其重新插入到父级别。使用 "Value" 属性,我可以随心所欲地覆盖整个值元素,前提是我将整个 {"Key":"", "Value":""}
对象传递给函数。在这种情况下,使用对象数组方法要干净得多。
我还基于堆栈溢出上的大量其他响应对数组进行了此更改,这鼓励使用它们而不是对象。
如果您要做的只是遍历对象,那么对象数组更有意义。如果这些是设置并且人们需要查找特定的设置,那么原始对象表示法会更好。原来允许人们编写代码
var foo = settings['2013'][someEventName].data1
而从对象数组中获取该数据需要遍历它们以找到具有键的那个:2013,这取决于列表的长度会导致性能问题。
向对象推送新数据就像
一样简单
settings['2014'] = {...}
并且从对象中删除数据也很简单
delete settings['2014']
我目前正在编写一个 GUI,它基本上允许用户使用 AJAX edit/populate/delete 一些设置文件,这些设置存储在 JSON 中。
我对 JavaScript 的经验有限(坦率地说,我对 MATLAB 以外的任何东西都没有什么经验),但是由于处理包含更多对象的对象的语义,我发现自己正在重构我的设置结构,而不是一组对象。在 C# 中,我会使用 KeyValuePair 来执行此操作,但是 JSON 结构阻止我做我真正想在这里做的事情,我想知道在 JavaScript 我现在应该采用它,而不是进行这些更改并发现我造成的问题多于我解决的问题。
样本数据结构与我的许多结构具有相似的要求,它接受任意年数,在这些任意数量的事件中,在这些事件中接受一定数量的值。
这是之前的结构:
{"2013":
{
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...},
...}
这是我的理想结构,其中 year/event 名称作为数组类型值的字符串类型键:
["2013":
[
"someEventName":
{
"data1":"foo",
"data2":"bar",
...},
...],
...]
据我所知,这将是无效的 JSON 表示法,所以这是我建议的结构:
[{"Key":"2013",
"Value":
[{"Key":"someEventName",
"Value":
{
"data1":"foo",
"data2":"bar",
...}
},
...]
},
...]
关于某物应该是包含对象的对象还是对象数组,我的建议"test"是"does my sub-structure take a fixed, known number of objects?"如果是,则设计为包含对象的对象;如果不是,设计成对象数组。
我需要经常过滤此结构以找到 data/values,并且我不打算利用使用数组带来的索引功能,但是从数组中推送和删除数据要多得多比对象更灵活,感觉使用包含对象的对象偏离了 OOP 的 class 模型;另一方面,如果它是一个包含对象的对象,通过 "Key" 查找我的数据的方法似乎都更简单,而且我不打算自己在这些对象上使用 Prototype 方法,所以谁关心破坏 OOP。
回复 1
例如,在前面的结构中添加年份,代码为 OBJ["2014"]={}
;在新结构中它将是 OBJ.push({"Key":"2014", "Value":{}})
;这两种解决方案都同样缺乏复杂性。
在这两种情况下删除同样微不足道。
但是,如果我想操纵事件的值,比如说,使用函数,如果我将指向该对象的指针传递给函数并尝试取代引用中的整个对象,它不会工作:我被迫复制原始事件(使用 jQuery 或更糟)并将其重新插入到父级别。使用 "Value" 属性,我可以随心所欲地覆盖整个值元素,前提是我将整个 {"Key":"", "Value":""}
对象传递给函数。在这种情况下,使用对象数组方法要干净得多。
我还基于堆栈溢出上的大量其他响应对数组进行了此更改,这鼓励使用它们而不是对象。
如果您要做的只是遍历对象,那么对象数组更有意义。如果这些是设置并且人们需要查找特定的设置,那么原始对象表示法会更好。原来允许人们编写代码
var foo = settings['2013'][someEventName].data1
而从对象数组中获取该数据需要遍历它们以找到具有键的那个:2013,这取决于列表的长度会导致性能问题。
向对象推送新数据就像
一样简单settings['2014'] = {...}
并且从对象中删除数据也很简单
delete settings['2014']