【问题标题】:Deserialization of partially flattened JSON部分扁平化 JSON 的反序列化
【发布时间】:2025-12-04 13:20:02
【问题描述】:

我有一个遗留 API 端点,不幸的是,它只支持平面 JSON 对象的输出。它的一个输出如下所示。

{
    "objects": [
        {
        "id": "1",
        "last-modified": "0",
        "created": "1",
        "name": "Test",
        "fields": "{\"k\":\"v\",\"k2\":\"v2\",\"k3\":[1,2,3],\"k4\":{}}"
        }
    ],
    "attribs": {}
}

虽然这是有效的 JSON,但对象的任何嵌套部分都将被字符串化并作为只有一键深度的整体对象返回。当我的 JS 检索此对象时,我尝试使用我编写的递归函数反序列化该对象的所有可反序列化部分。

var loads = function (obj) {
    var i, buffer;
    if (obj instanceof Array) {
        buffer = [];
        for (i = 0; i < obj.length; i++) {
            buffer.push(loads(obj[i]));
        }
        return buffer;
    } else if (obj instanceof Object) {
        buffer = {};
        for (i in obj) {
            if (obj.hasOwnProperty(i)) {
                buffer[i] = loads(obj[i]);
            }
        }
        return buffer;
    } else if (typeof obj === 'string') {
        return JSON.parse(obj);
    } else {
        return JSON.parse(obj);
    }
};

很明显递归是错误的,因为这个函数抛出了很多“unexpected token”和“unexpected identifier”的错误。

我在这个函数中犯了什么错误,阻止了字符串化 JSON 值的完全嵌套反序列化?

【问题讨论】:

  • 你不能简单地解析fields键:JSON.parse(answer.fields);吗?
  • @nietonfir 不......不幸的是,这个示例 json 已被大大简化,仅显示我当前挑战的一个示例。

标签: javascript json


【解决方案1】:

使用 JSON.parse 的第二个参数来简单地在安全的 try 块中恢复您的代码:

JSON.parse( strOfJSON,  function(k,v){
  try{v=JSON.parse(v)}catch(y){}
 return v
});

OP 测试代码输出:

{
    "objects": [
        {
            "id": 1,
            "last-modified": 0,
            "created": 1,
            "name": "Test",
            "fields": {
                "k": "v",
                "k2": "v2",
                "k3": [
                    1,
                    2,
                    3
                ],
                "k4": {}
            }
        }
    ],
    "attribs": {}
}

您可以通过尝试将 json 作为字符串来识别并跳过 try{},但这个简单的天真代码可以工作,并展示了如何使用本机 JSON.parse() 函数来执行您想要的操作。

【讨论】:

  • 像魅力一样工作——也了解了 reviver 功能!今天是个好日子。