为什么我不能使用substr抹掉最后一个“,”

时间:2019-05-02 15:24:21

标签: php arrays json

我想用JSON编码一些数据并将其发送到前端Javascript。我所在的服务器不支持本机json_encode()功能,因此我尝试自己编写它,但是遇到数据格式问题。

我尝试了substr(),但是似乎没有用。

function json_readable_encode($in, $indent = 0, $from_array = false)
{
    $_myself = __FUNCTION__;
    $_escape = function ($str)
    {
        return preg_replace("!([\b\t\n\r\f\"\\'])!", "\\\\\\1", $str);
    };

    $out = '';

    foreach ($in as $key=>$value)
    {

        $out .= str_repeat("\t", $indent + 1);
       $out .= "\"".$_escape((string)$key)."\": ";

        if ( is_object($value) ||is_array($value))
        {
            $out .= "\"\n\"";
            $out .= $_myself($value, $indent + 1);
        }
        elseif (is_bool($value))
        {
            $out .= $value ? 'true' : 'false';
        }
        elseif (is_null($value))
        {
            $out .= 'null';
        }
        elseif (is_string($value))
        {
            $out .= "\"" . $_escape($value) ."\"";
        }
        else
        {
            $out .= $value;
        }

        $out .= ",\n";

    }

    if (!empty($out))
    {
        $out = substr($out, 0, -2);
    }

    $out = str_repeat("\t", $indent) . "{\n" . $out;
    $out .= "\n" . str_repeat("\t", $indent) . "},";
    $str = $out;
    echo $out;
}

我期望格式正确的东西:

[{ "Catogory": "Sedan", "Availability": "True", "Brand": "Toyota", "Model": "Camry", "Modelyear": "2013", "mileage": "85364", "FuelType": "petrol", "Seats": "5", "PricePerDay": "240", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Camry.jpg" },   { "Catogory": "SUV", "Availability": "True", "Brand": "Nissan", "Model": "X-trail", "Modelyear": "2015", "mileage": "36782", "FuelType": "petrol", "Seats": "7", "PricePerDay": "360", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/X-trail.jpg" },   { "Catogory": "Sedan", "Availability": "False", "Brand": "Volkswagen", "Model": "Golf", "Modelyear": "2017", "mileage": "13586", "FuelType": "CNG", "Seats": "5", "PricePerDay": "180", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Golf.png" }, { "Catogory": "Sedan", "Availability": "False", "Brand": "Honda", "Model": "Civic", "Modelyear": "2018", "mileage": "9586", "FuelType": "petrol", "Seats": "5", "PricePerDay": "220", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Civic.jpg" },  { "Catogory": "Sedan", "Availability": "True", "Brand": "BMW", "Model": "320i", "Modelyear": "2013", "mileage": "5209", "FuelType": "petrol", "Seats": "5", "PricePerDay": "150", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/320i.jpg" },   { "Catogory": "SUV", "Availability": "True", "Brand": "Benz", "Model": "GLC", "Modelyear": "2014", "mileage": "23665", "FuelType": "petrol", "Seats": "5", "PricePerDay": "170", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/GLC.png" }, { "Catogory": "SUV", "Availability": "True", "Brand": "Jeep", "Model": "GLC", "Modelyear": "2019", "mileage": "999", "FuelType": "petrol", "Seats": "5", "PricePerDay": "130", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Cherokee.png" },  { "Catogory": "SUV", "Availability": "True", "Brand": "Suzuki", "Model": "Jimny", "Modelyear": "2009", "mileage": "50006", "FuelType": "petrol", "Seats": "5", "PricePerDay": "80", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Jimny.jpg" },{ "0": " ", "1": " ", "2": " ", "3": " ", "4": " ", "5": " ", "6": " ", "7": " " }]

所以我尝试了

echo "[";
echo json_readable_encode($carlist, $indent = 0, $from_array = false);
echo "]";

输出为:

[   { "Catogory": "Sedan", "Availability": "True", "Brand": "Toyota", "Model": "Camry", "Modelyear": "2013", "mileage": "85364", "FuelType": "petrol", "Seats": "5", "PricePerDay": "240", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Camry.jpg" }, { "Catogory": "SUV", "Availability": "True", "Brand": "Nissan", "Model": "X-trail", "Modelyear": "2015", "mileage": "36782", "FuelType": "petrol", "Seats": "7", "PricePerDay": "360", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/X-trail.jpg" },   { "Catogory": "Sedan", "Availability": "False", "Brand": "Volkswagen", "Model": "Golf", "Modelyear": "2017", "mileage": "13586", "FuelType": "CNG", "Seats": "5", "PricePerDay": "180", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Golf.png" }, { "Catogory": "Sedan", "Availability": "False", "Brand": "Honda", "Model": "Civic", "Modelyear": "2018", "mileage": "9586", "FuelType": "petrol", "Seats": "5", "PricePerDay": "220", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Civic.jpg" },  { "Catogory": "Sedan", "Availability": "True", "Brand": "BMW", "Model": "320i", "Modelyear": "2013", "mileage": "5209", "FuelType": "petrol", "Seats": "5", "PricePerDay": "150", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/320i.jpg" },   { "Catogory": "SUV", "Availability": "True", "Brand": "Benz", "Model": "GLC", "Modelyear": "2014", "mileage": "23665", "FuelType": "petrol", "Seats": "5", "PricePerDay": "170", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/GLC.png" }, { "Catogory": "SUV", "Availability": "True", "Brand": "Jeep", "Model": "GLC", "Modelyear": "2019", "mileage": "999", "FuelType": "petrol", "Seats": "5", "PricePerDay": "130", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Cherokee.png" },  { "Catogory": "SUV", "Availability": "True", "Brand": "Suzuki", "Model": "Jimny", "Modelyear": "2009", "mileage": "50006", "FuelType": "petrol", "Seats": "5", "PricePerDay": "80", "Description": "XXXXXXXXXXXXXXXXX", "imageurl": "/carrental/images/Jimny.jpg" },{ "0": " ", "1": " ", "2": " ", "3": " ", "4": " ", "5": " ", "6": " ", "7": " " },]

输出末尾有一个额外的“,”,因此会出现错误:

Uncaught SyntaxError: Unexpected token 
 in JSON at position 2285
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.xmlhttp.onreadystatechange

有人建议进行这项工作吗?

1 个答案:

答案 0 :(得分:0)

您的最初问题是,您没有尝试从外部对象列表中删除逗号,该对象在代码末尾插入。您(正确)使用substr()仅影响内部对象。您无法轻易删除该最后的逗号;因为这是一个递归函数,所以您没有办法知道最终元素将是什么,因此必须在函数外部完成。我将您的函数包含在_encode()类中,然后使面向公众的函数引用该函数,并使用rtrim()处理逗号。请注意,您还必须修剪递归调用的输出。

您的转义功能无法正常工作。因为您使用的是双引号引起来的字符串,所以\t\n等被解释为文字制表符和换行符。然后,您只需在它们前面加上一个反斜杠,而不是用适当的转义序列替换它们。另外,某些非PHP转义序列(例如\b)已由正则表达式解释,因此您可能会转义不需要转义的内容。一个简单的str_replace消除了使用正则表达式的所有问题。

我删除了缩进输出的代码。 JSON首先是一种数据传输格式,如果您需要阅读它,那么可以使用一些工具。尝试在此处的代码中这样做只会增加出错的可能性,并使代码更加复杂。

您应始终从函数中return个值,不要回显它们。

我现在唯一缺少的就是输出JSON数组的能力。快速浏览这些键以检查是否只有数字,然后设置一个标志,这将是我对这段代码的下一步改进。

<?php
class JSON
{
    public static function encode($in)
    {
        $output = self::_encode($in);
        $output = "[" . rtrim($output, ",") . "]";
        return $output;
    }
    private static function _escape($str)
    {
        // escape values with special escape sequences
        $search  = ["\\",   "\"",   "/",   "\r",  "\n",  "\t",  "\f",  chr(8)];
        $replace = ["\\\\", "\\\"", "\\/", "\\r", "\\n", "\\t", "\\f", "\\b"];
        // escape other control chars with numeric escape sequences
        for ($i = 0; $i <= 31; $i++) {
            $search[] = chr($i);
            $replace[] = sprintf("\\u%04x", $i));
        }

        return str_replace($search, $replace, $str);
    }

    private static function _encode($in)
    {
        $out = "";
        $start_delimiter = "{";
        $end_delimiter = "}";

        foreach ($in as $key=>$value) {
            $out .= "\"" . self::_escape($key) . "\":";

            if (is_object($value) || is_array($value)) {
                $out .= rtrim(self::_encode($value), ",");
            }
            elseif (is_bool($value)) {
                $out .= $value ? 'true' : 'false';
            }
            elseif (is_null($value)) {
                $out .= 'null';
            }
            elseif (is_string($value)) {
                $out .= "\"" . self::_escape($value) . "\"";
            }
            else {
                $out .= $value;
            }
            $out .= ",";
        }

        $out = rtrim($out, ",");

        $out = $start_delimiter . $out . $end_delimiter . ",";
        return $out;
    }
}

header("Content-Type: application/json");    
echo JSON::encode($carlist);