SQL行的JSON问题返回

时间:2015-09-23 16:53:32

标签: sql json parsing

我尝试解析JSON时遇到问题。我用PHP创建了我的JSON“by my hand”: $outp ='{"records":['.$outp.']}';我创建了它,因此我可以从我的数据库中取字段以在页面中显示它们。问题是,在我的数据库中,我有一个字段“描述”,人们可以在其中对某些内容进行描述。所以有些人会像这样返回到行:

Interphone

Equipe:
Canape-lit

Autre:
Local

当我尝试解析我的JSON时,由于这些行的返回而出现错误。 “SyntaxError:意外的令牌”。

以下是我的JSON示例:

{"records":[{"Parking":"Aucun","Description":"Interphone

Equipé :
Canapé-lit

","Chauffage":"Fioul"}]}

有人能帮助我吗?

1 个答案:

答案 0 :(得分:1)

你真的把自己挖到了一个非常糟糕的洞里。

问题

您遇到的问题是换行符(换行符和回车符)是无效的JSON。必须将其转义为\n\r。您可以在此处查看完整的JSON标准here

你需要做两件事。

修复您的代码

尽管JSON标准相对简单,但您应该手动创建JSON。你已经知道为什么了。你必须处理几个边缘情况等。您的用户可以在页面上输入任何,您需要确保无论如何都能正确编码。

您需要使用JSON序列化工具。 json_encode自5.2起构建。如果您出于任何原因无法使用此功能,请使用JSON序列化程序查找现有的,广泛使用的(因此经过严格测试的)第三方库。

如果您要问,"为什么我不能创建自己的序列化程序?",理论上你可以。实际上,没有意义。你的胜利不如现有的好。与许多人在生产中使用的东西相比,它更容易出现错误并且表现更差。创建和测试也需要比使用现有的更长的时间。

如果在将数据从数据库中拉出后需要在代码中使用此数据,那么您需要一个JSON反序列化器。 json_decode也应该没问题,但如果你不能使用它,那就找一个广泛使用的第三方库。

修复数据

如果你还没有投入生产,你真的在​​这里躲过了一个子弹,你可以跳过整个部分。如果您已经投入生产并且有来自用户的数据,那么您就会遇到一个重大问题。

即使您修复了代码,您的生产数据库中仍然会有错误的数据无法正确解析。您做某事来使这些数据可用。不幸的是,不可能为每种可能的情况自动恢复原始数据。这是因为用户可能已输入您添加到数据中的字符/子字符串,以将其转换为" JSON&#34 ;;例如,他们可能输入了以逗号分隔的引用词组列表:"dog","cat","pig", and "cow"。这是一个棘手的问题,因为你知道你没有正确地序列化所有输入输入。没有办法区分生成的代码文本和用户输入的文本之间的区别。当你无法在代码中解决问题时,你将不得不尽心尽力并尝试抛出错误,并且在某些特殊情况下它可能会弄乱用户的数据。您可能需要手动修复一些事情。

首先与您的经理,团队负责人讨论此事,无论您回答谁。假设您无法丢失数据,这是为数据创建修补程序时最合理的流程:

  1. 创建生产数据的数据库转储。
  2. 将该转储导入开发数据库。
  3. 从最后一步开发并测试您在开发数据库中修复此数据的方法。
  4. 确保您有部署错误的恢复计划。在您的测试环境中测试该计划。
  5. 一旦您完成了典型的发布流程,就可以一起发布固定代码和数据更新。
  6. 让网站离线。
  7. 备份数据库。
  8. 使用新代码更新网站。
  9. 实施数据修复。
  10. 确认它有效。
  11. 将网站上线。
  12. 如果您的数据修复无效(可能是因为您没有想到边缘情况或其他内容),那么您可以恢复一个很好的备份,并且可以取消发布。然后回到第1步。

    至于如何你可以修复数据,我不建议在这里查询。我推荐一个小脚本工具。它必须从数据库加载数据,拉开字符串,尝试识别所有部分,从这些部分构建对象,最后将它们正确地序列化为JSON,然后将它们放回数据库中。

    这是一个关于如何将字符串分开的示例函数:

    const ELEMENT_SEPARATOR = '","';
    const PAIR_SEPARATOR = '":"';
    
    function recover_object_from_malformed_json($malformed_json, $known_keys) {
        $tempData = substr($malformed_json, 14); // Removes {"records":[{" prefix
        $tempData = substr($tempData, 0, -4); // Removes "}]} suffix
        $tempData = explode(ELEMENT_SEPARATOR, $tempData); // Split into what we think are pairs
    
        $data = array();
        $lastKey = NULL;
    
        foreach ($tempData as $i) {
            $explodedI = explode(KEY_VALUE_SEPARATOR, $i, 2); // Split what we think is a key/value into key and value
            if (in_array($explodedI[0], $known_keys)) { // Check if it's actually a key
                // It's a key
                $lastKey = $explodedI[0];
                if (array_key_exists($lastKey, $data)) {
                    throw new RuntimeException('Duplicate key: ' + $lastKey);
                }
                // Assign the value to the key
                $data[$lastKey] = $explodedI[1];
            }
            else {
                // This isn't a key vlue pair, near as we can tell
                // So it must actually be part of the last value,
                // and the user actually entered the delimiter as part of the value.
                if (is_null($lastKey)) {
                    // This one is REALLY messed up
                    throw new RuntimeException('Does not begin with a known key');
                }
    
                $data[$lastKey] += ELEMENT_SEPARATOR;
                $data[$lastKey] += $i;
            }
        }
    
        return $data;
    }
    

    请注意,我假设你的"列表"是一个单一的元素。如果您有多个,这会变得更加困难和麻烦。您还需要提前知道您希望拥有哪些密钥。最重要的是,您必须撤消您的代码所做的任何事情,以创建" JSON",并且您必须尽一切努力来尽量不让用户陷入困境&#39 ; s数据。

    您可以使用以下内容:

    $knownKeys = ["Parking", "Description", "Chauffage"];
    
    // Fetch your rows and loop over them
    foreach ($dbRows as $row) {
        try {
            $dataFromDb = $row.myData // or however you would pull out this string.
            $recoveredData = recover_object_from_malformed_json($dataFromDb);
    
            // Save it back to the DB
            $row.myData = json_encode($recoveredData);
            // Make sure to commit here.
        }
        catch (Exception $e) {
            // Log the row's ID, the content that couldn't be fixed, and the exception
            // Make sure to roll back here
        }
    }
    

    (请原谅我,如果数据库的东西看起来真的很糟糕。我不做PHP,所以我不知道代码应该怎么样。希望你至少可以得到这个概念。)

    为什么我不建议尝试将您的数据解析为JSON以恢复它。

    底线是您的数据库中的数据不是 JSON。如果您尝试解析它,那么您没有正确处理的所有其他边缘情况将在此过程中被搞砸。你会看到像

    这样的坏事
    • \\变为\
    • \j变为j
    • \t成为制表符

    最后,它会使你的数据更加混乱。

    结论

    这是一个巨大的混乱,您应该从不尝试将某些内容转换为标准格式,而无需使用经过适当构建且经过良好测试的序列化程序。修复数据会很困难,而且需要时间。我也非常怀疑你在文本处理技术方面有很多背景,而缺乏这些知识会使这更难。通过研究编译器的制作方法,您可以获得有关文本处理的一些好信息。祝你好运。