【问题标题】:How do I encode a highly nested php array/object into JSON?如何将高度嵌套的 php 数组/对象编码为 JSON?
【发布时间】:2020-07-30 18:19:21
【问题描述】:

注意:这似乎很长,这里有一个简短的解释,供那些不想(或不需要)看到我所有冗长解释的人在下面。如果我在这里放太多东西,我很抱歉,但我认为提供太多信息比提供太多信息要好。

简而言之,我有一个充满对象的 JS 数组。这些对象具有数组作为它们的一些属性。这些数组是对象,里面有数组,里面有对象。总而言之,有5层嵌套。 JavaScript 的 JSON.parse/stringify 在这些上工作得很好,但是当开始让这个程序在服务器上工作时,我使用 JavaScript 的 JSON.stringify 发送一些数据并使用 php 的 json_decode 来读取它。 php 处理数据,使用它来编辑大对象(以 JSON 格式存储在服务器上的 txt 文件中)。像 addMessage 和 createRoom 这样的小功能确实可以工作,但是当我尝试发送一个 3 级对象时它不起作用。我认为问题可能与尝试上传字符串化对象有关,因为我的其他 php 脚本接收参数,然后将这些对象创建为 stdClass。

无聊的版本:

这个问题似乎在其他地方以变体形式提出,但我找不到适合我的答案。基本上,我正在开发一个在线交互式白板程序。它使用 JS 作为主要语言,使用 PHP 来完成所有的文件编写工作。我使用 json_encode 将数据存储在 .txt 文件中。要从文件中读取数据,我的 JS 调用我的 php,它对文件进行解码、获取相关数据、对其进行编码并对其进行回显。所有的数据都是由 JS 制作的,并且是面向被 JS 编辑的——所有的数据都是由 JS Classes 构建的。到目前为止,我的程序运行良好,加入/创建白板和聊天功能相对简单。当我尝试实现跨计算机的白板同步时,我发现当我将新的白板数据发送到 php 并尝试将其放入文件时,json_encode 失败。我从 Apache 日志中收到此错误:PHP Recoverable fatal error: Object of class stdClass could not be converted to string
它没有停止程序,而是继续并破坏数据文件(可能需要在那里进行一些检查)并杀死整个程序。 这就是我的数据结构的工作方式(在 JS 中,就像我硬编码它一样):

[ /* list of room objects */
    { /* a room object */
        name: 'example', 
        id: 'numbers', 
        whiteboardData: [
            { /* a shape object */
            color: [r, g, b],
            pointList: [
                { /* a vector object*/
                    x: 100,
                    y: 100,
                }
                /* heaps of other vector objects */
            ]
            }
        ], /* end of whiteboardData */
        chatMessages: [
            { /* a message object */
                sender: 'username',
                content: 'hi'
            }
            /* heaps of other message objects */
        ]
    }
    /* heaps of other room objects */
]

正如我所说,消息的 3 级嵌套可以正常工作,但点坐标的 5 级嵌套不起作用。如果不重写大部分程序,我就无法简化程序的数据存储。 我的 php 伪代码(因为如果不阅读我的文档,代码有点难以理解):

receive id of the room that the whiteboard belongs to
receive whiteboard data as object
receive username of who made the edit (not used yet)

get contents of data file on server
do checks

decode data file and turn into object (roomData)
get the room as an object (actually a link to the room object in roomData)

decode the data that got sent up and turn into object
swap out the whiteboardData of the room object with the new data made in the line above

turn the main object (roomData) into a string (this is the one that keeps failing)
put the resulting string into the file

我的 php:

<?php
const roomDataFileUrl = "../!roomdata.txt";

$roomId = $_POST["roomId"];
$whiteboardDataStr = $_POST["whiteboardData"];
$editMadeBy = $_POST["editMadeBy"]; // unused as of now, may be used later on

// read data from file
$roomDataStr = file_get_contents(roomDataFileUrl);

if (strlen($roomDataStr) <= 0) {
    echo "||nonExistentRoom";
}

// do check for null
if ($roomDataStr !== null) {
    // if data file is empty, then just make empty array for data instead of reading file
    if (strlen($roomDataStr) <= 0) {
        $roomData = [];
    }
    else { // otherwise parse data
        $roomData = json_decode($roomDataStr);
    }

    $room = getRoom($roomData, $roomId);

    // check if room exists
    if ($room !== null) {
        // parse the whiteboard data and then put it in the room
        // this will kill the program is there's a problem with the whiteboard data, so no checks needed
        $whiteboardData = json_decode($whiteboardDataStr);
        $room->whiteboardData = $whiteboardData;



        // THIS LINE IS THE ONE THAT KEEPS FAILING
        $roomDataStr = json_encode($roomData);



        // put in file
        if (strlen($roomDataStr) > 0) {
            file_put_contents(roomDataFileUrl, $roomData);
        }
        else {
            echo "**unknownServerError";
        }
    }
    else {
        echo "||nonExistentRoom";
    }
}
else {
    echo "**roomFileEmpty";
}

function getRoom($roomData, $roomId) {
    $room = null;
    for ($i = 0; $i < count($roomData); $i ++) {
        $currentRoom = $roomData[$i];
        if ($currentRoom->id === $roomId) {
            $room = $currentRoom;
            break;
        }
    }
    return $room;
}

?>

我的 JS(一个类中的两个方法被剪辑和编辑,因为大部分方法都不需要)

drawWhiteboardData(serverResponse) {
  // I've removed about 20 lines of error processing here
  var whiteboardDataStr = response;
  var whiteboardData = JSON.parse(whiteboardDataStr);
  this.whiteboardPtr.shapeList = whiteboardData;
}

sendWhiteboardData() {
  var localWhiteboardData = this.whiteboardPtr.shapeList;
  // this stringify works fine - I've checked the output manually
  var localWhiteboardDataStr = JSON.stringify(localWhiteboardData);

  // serverCommsManager.sendWhiteboardData just turns the data into a post request and sends it to my php file using the keys that can be seen at the top of the php file
  this.serverCommsManagerPtr.sendWhiteboardData(
    localWhiteboardDataStr, this.successfulEditProtocol.bind(this));
  this.lastWhiteboardUpload = localWhiteboardDataStr;
}

【问题讨论】:

    标签: javascript php arrays json ajax


    【解决方案1】:

    那里的噪音太大,我无法轻易看出问题所在。

    与其试图推理,我只是向您展示一个解决方案,它接收数据就像您硬编码它一样,在返回之前向whiteboardData 数组添加一个新元素。我希望使用 fetch 而不是旧的 XMLHttpRequest,但有点生疏。这对我来说更容易。

    HTML

    <!doctype html>
    <html>
    <head>
    <script>
    "use strict";
    function byId(id){return document.getElementById(id)}
    window.addEventListener('load', onLoaded, false);
    
    var jsonObj = 
    [ /* list of room objects */
        { /* a room object */
            name: 'example', 
            id: 'numbers', 
            whiteboardData: [
                { /* a shape object */
                color: [100, 150, 100],
                pointList: [
                    { /* a vector object*/
                        x: 100,
                        y: 100,
                    }
                    /* heaps of other vector objects */
                ]
                }
            ], /* end of whiteboardData */
            chatMessages: [
                { /* a message object */
                    sender: 'username',
                    content: 'hi'
                }
                /* heaps of other message objects */
            ]
        }
        /* heaps of other room objects */
    ];
    
    function ajaxPostFormData(url, formData, onSuccess, onError)
    {
        var ajax = new XMLHttpRequest();
        ajax.onload = function(){onSuccess(this);}
        ajax.onerror = function(){onError(this);}
        ajax.open("POST",url,true);
        ajax.send(formData);
    }
    
    function onLoaded(evt)
    {
        let fd = new FormData();
        fd.append('whiteboardData', JSON.stringify(jsonObj) );
        ajaxPostFormData('blahBlah.php', fd, function(ajax){console.log(ajax.responseText)}, function(){} );
    }
    </script>
    </head>
    <body>
    </body>
    </html>
    

    PHP

    <?php
    // blahBlah.php
        var_dump($_POST['whiteboardData']);
    
        $jsonObj = json_decode( $_POST['whiteboardData'] );
    
        $newObj = new wbData(200,300,200, [new vec2d(0,0), new vec2d(10,10), new vec2d(100,100)] );
    
        // append the new stuff
        $jsonObj[0]->whiteboardData[] = $newObj;
    
        var_dump( json_encode($jsonObj) );
    
    //-----------------------------------
        class wbData
        {
            public function __construct ($r,$g,$b, $pts=[])
                {
                    $this->color = [$r, $g, $b];
                    //$this->pointList = [];
                    $this->pointList = $pts;
                }
        };
    
        class vec2d
        {
            public function __construct($x=0, $y=0)
            {
                $this->x = $x;
                $this->y = $y;
            }
        }
    ?>
    

    结果在控制台

    string(164) "[{"name":"example","id":"numbers","whiteboardData":[{"color":[100,150,100],"pointList":[{"x":100,"y":100}]}],"chatMessages":[{"sender":"username","content":"hi"}]}]"
    string(250) "[{"name":"example","id":"numbers","whiteboardData":[{"color":[100,150,100],"pointList":[{"x":100,"y":100}]},{"color":[200,300,200],"pointList":[{"x":0,"y":0},{"x":10,"y":10},{"x":100,"y":100}]}],"chatMessages":[{"sender":"username","content":"hi"}]}]"
    

    【讨论】:

    • 好的,谢谢,我修改了它以在我的情况下工作得更好,它工作了
    猜你喜欢
    • 2018-10-09
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2018-06-30
    相关资源
    最近更新 更多