为啥 JSON 没有关联数组?

Posted

技术标签:

【中文标题】为啥 JSON 没有关联数组?【英文标题】:Why doesn't JSON have associative arrays?为什么 JSON 没有关联数组? 【发布时间】:2015-01-14 03:42:00 【问题描述】:

为什么 JSON 没有关联数组? YAML 可以。

你不能在 JSON 中这样做:


    productsBySku: [
        12J432: 
            price: 49.99,
            qty_in_stock: 4
        ,
        5X4352: 
            price: 29.99,
            qty_in_stock: 5
        
    ]

但是在 YAML 中你可以这样做:

productsBySku:
  - 12J432: 
        price: 49.99,
        qty_in_stock: 4
  - 5X4352:
        price: 29.99,
        qty_in_stock: 5

从技术层面上来说,我想知道为什么会为 JSON 做出这个决定。

【问题讨论】:

JSON 有“关联数组”,它们被称为“对象”。您的 YAML 示例实际上是一个包含两个对象的数组,因此在 JSON 中它将是:"productsBySku": [ "12J432": ... , "5X4352": ... ] 为什么不呢?因为 JSON 在设计上是 javascript 的一个子集。而且 JavaScript 没有关联数组,无论其他人声称什么(对象属性没有排序)。 谢谢。如果这个问题不适合 SO,我很抱歉。老实说,我只是想了解事情背后的原因。 【参考方案1】:

因为 JSON 代表 JavaScript Object Notation 而 JavaScript 本身 具有对象 可以 关联数组一样工作,所以您可以这样做(注意我必须修复属性名称中缺少引号的问题才能生成有效的 JSON 样本):


    "productsBySku": 
        "12J432": 
            "price": 49.99,
            "qty_in_stock": 4
        ,
        "5X4352": 
            "price": 29.99,
            "qty_in_stock": 5
        
    

...您可以使用for..in 迭代对象属性:

for(var property in obj.propductsBySku) 
    // You don't want properties from the prototype
    if(obj.productsBySku.hasOwnProperty(property)) 
       var propertyValue = obj.productsBySku[property];
    

您还可以使用Object.keys(obj.productsBySku) 获取所有密钥。

OP 说...

但是 JSON 对象不能像关联数组一样使用,因为它们是 没订对吧?我的意思是你不能通过一个对象的 JavaScript 中的属性,如果它被视为关联 数组,你可以。我错了吗?

您说得对,但对象属性仍然可以使用 forEach 进行迭代:

// Object.keys will return an array of own object property names
Object.keys(obj).forEach(function(propertyName) 
   var propertyValue = obj[propertyName];
);

对象也可以像散列或关联数组一样使用,但不能依赖顺序。

【讨论】:

但是 JSON 对象不能像关联数组一样使用,因为它们没有排序,对吧?我的意思是你不能通过 JavaScript 中对象的属性来执行 forEach,如果它被视为关联数组,你可以。我错了吗? @CommaToast 我更新了我的答案,向您展示如何使用forEach 好的,我接受 forEach 可以这样使用。我仍然不知道为什么你不能有一个有序的地图,因为我希望能够有一个我可以在地图键或订单上使用点语法的地方。猜猜你不可能拥有一切。【参考方案2】:

为什么 JSON 没有关联数组?

JSON 没有 php 意义上的关联数组(例如,ordered 映射),但它肯定有键/值映射。它们被称为“对象”。

我在技术层面上想知道为什么会为 JSON 做出这个决定。

Crockford 将 JSON 设计为 JavaScript 对象初始化语法的子集。 JavaScript 没有关联数组(在有序映射的意义上),这毕竟是非常不寻常的,所以 JSON 没有。

YAML 可以

是吗? I'm not seeing them 和 Biffen seems to suggest otherwise。

阅读 YAML 规范,您的 YAML 完全等同于这个 JSON(一个对象数组,每个对象都有一个指向从属对象的键):


    "productsBySku": [
        
            "12J432": 
                "price": 49.99,
                "qty_in_stock": 4
            
        ,
        
            "5X4352": 
                "price": 29.99,
                "qty_in_stock": 5
            
        
    ]

即使 YAML 确实有它们,YAML 也不是 JSON[1]。 ;-) 它们是不同的数据符号,具有不同的设计目标。 XML 有名称空间,而 JSON 也没有。 YAML 支持通过引用重用节点,这允许循环结构,而 JSON 不支持。

你不能在 JSON 中这样做

这取决于你想要做什么。同样,据我所知,您的 YAML 与上面的 JSON 完全相同。

如果您的目标是按 SKU 列出该产品列表,您可以:


    "productsBySku": 
        "12J432": 
            "price": 49.99,
            "qty_in_stock": 4
        ,
        "5X4352": 
            "price": 29.99,
            "qty_in_stock": 5
        
    

productsBySku 属性是一个对象。它的属性不是ordered,所以它不是一个有序的map,而是一个map。如果您需要其中的属性具有顺序,则必须向它们添加一个属性,指示顺序是什么,然后在反序列化后应用该顺序。

或者,您可以使用数组,然后在反序列化后构建您的地图:


    "productsBySku": [
        
            "sku": "12J432",
            "price": 49.99,
            "qty_in_stock": 4
        ,
        
            "sku": "5X4352",
            "price": 29.99,
            "qty_in_stock": 5
        
    ]


[1]对于那些不知道的人,YAML 代表“YAML Ain't Markup Language”。

【讨论】:

【参考方案3】:

JSON 代表 JavaScript 对象表示法。正如它所说,它是一个类似结构的javascript对象。 在 JavaScript 中你没有associative arrays。但是你有 object 有类似的结构。

与您的示例非常相似,您可以:


"productsBySku": 
    "12J432": 
        "price": 49.99,
        "qty_in_stock": 4
    ,
    "5X4352": 
        "price": 29.99,
        "qty_in_stock": 5
    

【讨论】:

以上是关于为啥 JSON 没有关联数组?的主要内容,如果未能解决你的问题,请参考以下文章

验证 JSON 数组是不是有一个具有固定整数值的关联数组

JavaScript 关联数组到 JSON

检查 JSON 关联数组中是不是存在值

如何从android中的php关联数组解析JSON响应?

使用 RestKit 将 JSON“关联数组”映射到 CoreData

关联数组的json_decode