【问题标题】:Converting javascript object to JSON将 javascript 对象转换为 JSON
【发布时间】:2020-01-07 18:51:09
【问题描述】:

我有一个从 PHP 迁移到 Node.js 的应用程序。此应用程序将 javascript 对象作为数据发送到调用 PHP 处理程序的 ajax 函数。

然后,PHP 处理程序使用 PHP 的 json_encode 函数将对象转换为 JSON。 Node 有一个名为“json_encode”的包,但它与 PHP 对应的包不同。

基本上,我想转换这个:

{ 'pages[anycast][blocks][0][frames_content]': ' \n <section class="bg-white builder-bg padding-110px-tb xs-padding-60px-tb" . . . }

进入这个:

{"pages":{"anycast":{"blocks":[{"frames_content":"            \n            <section class=\"bg-white builder-bg padding-110px-tb xs-padding-60px-tb\" . . .}

在将其发送到服务器之前在客户端使用 JSON.stringify(data) 会创建以下内容:

{ '{"data":{"pages":{"anycast":{"blocks":[{"frames_content":" \n <section class': '\\"bg-white builder-bg padding-110px-tb xs-padding-60px-tb\\" . . . }

它添加了额外的反斜杠并错误地替换了后面的等号

客户端代码:

var pages = {}, theSite;
            if( site.sitePages[0].blocks.length !== 0 ) {
                for( var x = 0; x < site.sitePages.length; x++ ) {
                    if( site.sitePages[x].blocks.length !== 0 ) {
                        pages[site.sitePages[x].name] = site.sitePages[x].prepForSave();
                    } else {                
                        pages[site.sitePages[x].name] = 'empty';
                    }
                }

                theSite = {
                    pages: pages
                };

            } else {
                theSite = {
                    delete: true
                };
            }

            //remove old alerts
            $('#errorModal .modal-body > *, #successModal .modal-body > *').each(function(){
                $(this).remove();
            });

            $.ajax({
                url: 'https://api.handler.com/save',
                method: 'POST',
                data: theSite,
                dataType: "json"
            }).done(function (res) {
                //enable button
                $("a#savePage").removeClass('disabled');
                if( res.responseCode === 0 ) {
                    if( showConfirmModal ) {
                        $('#errorModal .modal-body').html( res.responseHTML );
                        $('#errorModal').modal('show');
                    }
                } else if( res.responseCode === 1 ) {
                    //no more pending changes
                    site.setPendingChanges(false);
                    $('body').trigger('changePage');
                }
            });
        },

        /*
            preps the site data before sending it to the server
        */
        prepForSave: function(template) {
            this.sitePagesReadyForServer = {};
            if( template ) {//saving template, only the activePage is needed
                this.sitePagesReadyForServer[this.activePage.name] = this.activePage.prepForSave();
                this.activePage.fullPage();
            } else {//regular save
                //find the pages which need to be send to the server
                for( var i = 0; i < this.sitePages.length; i++ ) {
                    if( this.sitePages[i].status !== '' ) {
                        this.sitePagesReadyForServer[this.sitePages[i].name] = this.sitePages[i].prepForSave();
                    }
                }
            }
        },

我通过 AJAX 将“theSite”变量发送到服务器。

原始 PHP 服务器端处理程序:

<?php
$return = [];

if( isset($_POST['data']) && $_POST['data'] != '' ) {

    if( isset($_POST['data']['delete']) ) {

        $myfile = fopen("site.json", "w");
        fwrite($myfile, '{}');
        fclose($myfile);

    } else {

        $myfile = fopen("site.json", "w");
        fwrite($myfile, json_encode($_POST['data']));
        fclose($myfile);

    }

    $return['responseCode'] = 1;
    $return['responseHTML'] = '<h5>Hooray!</h5> <p>The site was saved successfully!</p>';

} else {

    $return['responseCode'] = 0;
    $return['responseHTML'] = '<h5>Ouch!</h5> <p>Something went wrong and the site could not be saved :(</p>';

}
echo json_encode($return);
?>

【问题讨论】:

  • 看起来您将其序列化为字符串,而不是对象。因此,那些额外的字符。你能给我们一些代码吗?
  • 在哪里生成 pages[anycast][blocks][0][frames_content] - JS 中的客户端,您正试图将其转换为 JSON 以发送到 PHP 或服务器 -在 PHP 中,你正在尝试在 JS 中阅读它?
  • 不要认为它直接回答了您的问题,但可能值得查看 lodash 的 setsetWith 函数。
  • 显示您的原始 PHP 代码和试图替换它的 Node.js 代码。然后,我们可以向您展示您在转换中出了什么问题。
  • 您的原始转换看起来像是 PHP 使用 POST 或 GET 参数完成的那种解析。我认为没有任何内置的 JS 函数可以公开这种解析,但它大概是在 requests 模块内部完成的。

标签: javascript json


【解决方案1】:

编辑我会保留最初的答案,以防它对其他人有用。

如果您通过 Ajax 发送 JSON,并检查 $_POST['data'],则在 PHP 端只需发送到 json_decode($_POST['data'])

那时您将拥有一个 PHP stdClass 对象,其中包含您期望的所有字段,例如 $object-&gt;delete 或其他。

如果您更喜欢使用关联数组而不是对象,请使用json_decode($_POST['data'], true)

如果这仍然不是答案,也许您可​​以更好地详细说明您期望的确切输入和确切输出,因为我之前的回答是关于这个,正是您描述的 I/O。


假设您收到的对象键中没有花哨的字符,例如 'pages[anycast][blocks][0][frames_content]' 这样的内部键,您可以使用一些专门的约定来转换这些类型的键(通常来自旧的数据库或服务已经知道 JSON)转化为更递归的数据。

这只是一个例子:

const input = {'pages[anycast][blocks][0][frames_content]': 'value'};
const output = Object.keys(input).reduce(
  (js, key) => {
    let root = js;
    const keys = key
      .replace(
        /(\[|\]\[?)/g,
        ($0, $1) => $1 === ']' ? '' : '\x01'
      )
      .split('\x01');
    for (let i = 1, {length} = keys; i < length; i++) {
      const prev = keys[i - 1];
      if (!root.hasOwnProperty(prev))
        root[prev] = /^\d+$/.test(keys[i]) ? [] : {};
      root = root[prev];
    }
    root[keys.pop()] = input[key];
    return js;
  },
  {}
);

序列化的output 变量在解析后将如下所示:

{
  "pages": {
    "anycast": {
      "blocks": [
        {
          "frames_content": "value"
        }
      ]
    }
  }
}

当前示例假定放置在[0][1] 中的任何内容都应作为数组处理,而其他所有内容都应作为对象字段处理。

建议的转换使得每个索引也可以有多个条目:

const input = {
  'pages[anycast][blocks][0][frames_content]': 'first',
  'pages[anycast][blocks][1][frames_content]': 'second',
};

// ... after previous parsing, output will be
{
  "pages": {
    "anycast": {
      "blocks": [
        {
          "frames_content": "first"
        },
        {
          "frames_content": "second"
        }
      ]
    }
  }
}

当然,如果您有两次相同的字段名称,这些字段名称将被覆盖,但我相信如果您的对象来自旧服务,则永远不会出现这种情况,因为我认为它们已经找到了自己的架构。

【讨论】:

  • 您的回答产生了以下结果:
  • { pages: { anycast: { blocks: [Array] },错误:{ blocks: [Array] },下载:{ blocks: [Array] },检查:{ blocks: [Array] },索引:{块:[Array]},语音:{块:[Array]},家庭:{块:[Array]},牙科:{块:[Array]},callonly:{块:[Array] } } }
  • 我已经用我的少量输入提供了一个答案,如果有更好的输入会有更好的答案。不过,您在我回答后编辑了帖子,所以也许我会看看我能做什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-02
  • 2013-11-02
  • 1970-01-01
  • 2021-05-02
  • 2016-12-26
  • 2018-04-28
相关资源
最近更新 更多