简体   繁体   English

使用PHP的json_encode创建的JSON会导致解析错误

[英]JSON created with PHP's json_encode results in parse errors

Take the following PHP array: 采取以下PHP数组:

$arr = array(
    'about' => 'Ai você fala o seguinte: "- Mas vocês acabaram isso?" Vou te falar: -"Não, está em andamento!" Tem obras que "vai" durar pra depois de 2010. Agora, por isso, nós já não desenhamos, não começamos a fazer projeto do que nós "podêmo fazê"? 11, 12, 13, 14...',
    'construction' => 100,
);

When parsed to JSON with PHP's json_encode , I get the following string: 当使用PHP的json_encode解析为JSON时,我得到以下字符串:

[{"about": "Ai você fala o seguinte: \"- Mas vocês acabaram isso?\" Vou te falar: -\"Não, está em andamento!\" Tem obras que \"vai\" durar pra depois de 2010. Agora, por isso, nós já não desenhamos, não começamos a fazer projeto do que nós \"podêmo fazê\"? 11, 12, 13, 14...", "construction": 100}]

Note that the double quotes in the original string get escaped with a backslash. 请注意,原始字符串中的双引号会以反斜杠转义。 It looks good and even validates . 它看起来不错,甚至可以验证

When I try to parse the JSON in Chrome or Safari (using JSON.parse() ), I get the following error in the console: 当我尝试在Chrome或Safari中解析JSON(使用JSON.parse() )时,在控制台中出现以下错误:

Uncaught SyntaxError: Unexpected number

Firefox gives me: Firefox给了我:

SyntaxError: JSON.parse: expected ',' or '}' after property value in object at line 1 column 39 of the JSON data

From the Firefox error, I gather the first escaped double quote in the string seems to break the code. 由于Firefox错误,我在字符串中收集了第一个转义的双引号似乎破坏了代码。

If I manually escape the backslashes before the quotes, I get the expected object... 如果我手动在引号前转义反斜杠 ,则会得到预期的对象...

How can I prevent this error? 如何防止此错误? Am I doing something wrong? 难道我做错了什么?


Relevant code: 相关代码:

Model: 模型:

// Returns an array with basic enterprise information
public function getBasicInfo($destination = null)
{
    $response = array(
        'id' => $this->id,
        'name' => $this->name,
        'category' => ! empty($this->category_id) ? $this->category->name : '',
        'neighborhood' => ! empty($this->neighborhood) ? $this->neighborhood : '',
        'city' => (! empty($this->city) ? $this->city : '') . (! empty($this->state_id) ? (! empty($this->city) ? ', ' : '') . $this->state->abbreviation : ''),
        'dorms' => $this->dormitories_text,
        'area' => $this->area,
        'status' => ! empty($this->status_id) ? $this->status->name : '',
        'price' => $this->price > 0 ? 'R$ ' . number_format($this->price, 2, ',', '.') : '',
        'installment' => $this->installment > 0 ? 'R$ ' . number_format($this->installment, 2, ',', '.') : '',
        'image' => ! empty($this->card_image_id) && is_object($this->card_image) ? $this->card_image->getUrl() : '',
        'logo' => ! empty($this->logo_image_id) && is_object($this->logo_image) ? $this->logo_image->getUrl() : '',
        'permalink' => $this->getPermalink($destination),
        'about' => ! empty($this->about) ? $this->get_html($this->about) : '',
        'construction' => $this->getLatestConstructionStageProgress(),
    );
    return $response;
}

Controller: 控制器:

    // Build data array
    $json = array();
    foreach ($enterprises as $enterprise) {
        $json[] = $enterprise->getBasicInfo(REALTOR_URL);
    }
    $json = json_encode($json);

    // Build data array
    $data = array(
        'urlOrigin'     => $this->url_origin(),
        'module'        => 'Portal do Corretor - Empreendimentos',
        'categories'    => \Type::getByType('category'),
        'cities'        => \Enterprise::getUniqueCities(),
        'statuses'      => \Type::getByType('status'),
        'prices'        => \Enterprise::$priceRanges,
        'installments'  => \Enterprise::$installmentRanges,
        'neighborhoods' => $neighborhoods,
        'json'          => $json,
        'filters'       => (object) array(
            'search'        => isset($_POST['search']) && ! empty($_POST['search']) ? $_POST['search'] : null,
            'city'          => isset($_POST['city']) && ! empty($_POST['city']) ? $_POST['city'] : null,
            'neighborhood'  => isset($_POST['neighborhood']) && ! empty($_POST['neighborhood']) ? $_POST['neighborhood'] : null,
            'category'      => isset($_POST['category']) && ! empty($_POST['category']) ? intval($_POST['category']) : null,
            'dormitories'   => isset($_POST['dormitories']) && ! empty($_POST['dormitories']) ? intval($_POST['dormitories']) : null,
            'status'        => isset($_POST['status']) && ! empty($_POST['status']) ? intval($_POST['status']) : null,
        ),
        'sectionId'     => 'empreendimentos',
    );
    // Merge default values with the data array
    $data = array_merge($data, $this->getDefaultValues());

    // Returns the view with the data array
    return $this->view(REALTOR_URL . DS . 'empreendimentos', $data);

View: 视图:

<script type="text/javascript">
    var enterprises = '<?php echo $json; ?>';
</script>

JavaScript: JavaScript:

if ($('#enterprises') && $('#enterprise-template').length && 'undefined' !== typeof enterprises) {
    enterprises = JSON.parse(enterprises);
    enterprisesCount = enterprises.length;
}

You are not doing anything "wrong". 您没有做任何“错误”的事情。 In fact you have already found the solution yourself! 实际上,您已经自己找到了解决方案! The PHP-generated string is presumably transferred to JavaScript by echo -ing it into a line of JavasScript code using something like PHP生成的字符串大概是通过echo其传输到JavaScript的,使用类似以下内容的代码到一行JavasScript代码中

var jsvar='<?= json_encode($arr) ?>';

The result will look more or less like you have shown in your post: 结果看起来或多或少像您在帖子中显示的:

var js_var='[{"about": "Ai você fala o seguinte: \"- Mas vocês acabaram isso?\" Vou te falar: -\"Não, está em andamento!\" Tem obras que \"vai\" durar pra depois de 2010. Agora, por isso, nós já não desenhamos, não começamos a fazer projeto do que nós \"podêmo fazê\"? 11, 12, 13, 14...", "construction": 100}]';

When JavaScript parses this string the \\ before the " will be 'eaten up' and the JSON-string to be parsed by JSON.parse will look like: 当JavaScript解析此字符串时, "之前的\\将被“吃掉”,并且要由JSON.parse解析的JSON字符串如下所示:

'{"about":"Ai você fala o seguinte: "- Mas vocês acabaram isso?" Vou te falar: -"Não, está em andamento!" Tem obras que "vai" durar pra depois de 2010. Agora, por isso, nós já não desenhamos, não começamos a fazer projeto do que nós "podêmo fazê"? 11, 12, 13, 14...","construction":100}'

This string will understandably lead to error messages. 可以理解,该字符串将导致错误消息。

Solution: 解:

So, what you will have to do is mask all your \\ with addslashes() : 因此,您要做的就是用addslashes()屏蔽所有\\

var jsvar='<?= addslashes(json_encode($arr)) ?>';
var o=JSON.parse(jsvar);

Or, as @JAAulde quite correctly posted: you can skip the `string'-state of the variable altogether by doing directly: 或者,正如@JAAulde所正确介绍的那样:您可以通过直接执行以下操作来完全跳过变量的“字符串”状态:

var o=<?= json_encode($arr)) ?>;

Because JSON uses a subset of JS literal syntax, echoing it straight into the context of JS does not require any quote wrapping or parsing. 由于JSON使用JS文字语法的子集,因此直接将其回显到JS上下文中不需要任何引号包装或解析。

Outputting like this: 输出如下:

var enterprises = <?php echo $json; ?>;

Will cause the variable, enterprises , to be the data structure you desire once JS executes. JS执行后,将使变量enterprises成为您想要的数据结构。 As such, you also need to remove this line: 因此,您还需要删除以下行:

enterprises = JSON.parse(enterprises);

FWIW, your original error is caused by the need to double escape slashes in JS string literals. FWIW,您的原始错误是由JS字符串文字中的双转义斜杠引起的。 Because you outputted into a string literal, the single \\" is eaten up in the JavaScript execution and is no longer there for the JSON parse. To output into a JS string literal you would first need to escape the escapes. Thus, you should stick with my above changes (not to mention that my recommended changes require less overhead). 因为您已输出为字符串文字,所以在JavaScript执行中会吃掉单个\\" ,而不再用于JSON解析。要输出为JS字符串文字,您首先需要对转义符进行转义。因此,您应坚持使用我的上述更改(更不用说我建议的更改需要更少的开销)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM