【问题标题】:Need help sorting this logic with JSON Pretty Print需要帮助使用 JSON Pretty Print 对该逻辑进行排序
【发布时间】:2020-03-11 00:00:28
【问题描述】:

尝试漂亮地打印 json,并且工作正常,cept,似乎在打印每个对象数组之间的对象数组时添加了额外的一行。可以对这个逻辑使用一些帮助,因为我有一段时间没有触及这个......

漂亮的打印代码如下:

public function pretty_print($json_data, $line_numbers = true)
{
    $return = '';

    $space = 0;
    $flag = false;
    $json_data = trim($json_data);
    $line = 1;

    if (!empty($json_data)) {

        if (!empty($line_numbers))
            $return .= '<div class="line" data-line-number="' . $line . '">';

        //loop for iterating the full json data
        for($counter = 0; $counter < strlen($json_data); $counter++)
        {
            //Checking ending second and third brackets
            if ($json_data[$counter] == '}' || $json_data[$counter] == ']')
            {
                $space--;
                $line++;
                $return .= !empty($line_numbers) ? '</div><div class="line" data-line-number="' . $line . '">' : PHP_EOL;
                $return .= str_repeat(' ', ($space*4));
            }

            //Checking for double quote(“) and comma (,)
            if ($json_data[$counter] == '"' && ((!empty($counter) && $json_data[$counter-1] == ',') || ($counter > 1 && $json_data[$counter-2] == ',')))
            {
                $line++;
                $return .= !empty($line_numbers) ? '</div><div class="line" data-line-number="' . $line . '">' : PHP_EOL;
                $return .= str_repeat(' ', ($space*4));
            }
            if ($json_data[$counter] == '"' && !$flag)
            {
                if ( (!empty($counter) && $json_data[$counter-1] == ':') || ($counter > 1 && $json_data[$counter-2] == ':' ))
                    $return .= ' <span class="json-property">';
                else
                    $return .= '<span class="json-value">';
            }

            $return .= $json_data[$counter];

            //Checking conditions for adding closing span tag
            if ($json_data[$counter] == '"' && $flag) {
                $return .= '</span>';
            }
            if ($json_data[$counter] == '"')
                $flag = !$flag;

            //Checking starting second and third brackets

            if ($json_data[$counter] == '{' || $json_data[$counter] == '[')
            {
                $space++;
                $line++;
                $return .= !empty($line_numbers) ? '</div><div class="line" data-line-number="' . $line . '">' : PHP_EOL;
                $return .= str_repeat(' ', ($space*4));
            }
        }

        if (!empty($line_numbers))
            $return .= '</div>';
    }

    return !empty($return) ? trim($return) : json_encode(json_decode($json_data, true), JSON_PRETTY_PRINT);
}

但似乎用额外的&lt;div class="line" data-line-number=""&gt;&lt;/div&gt; 解析 json

这是一张图片,如果可能的话,想去掉数组对象之间的额外空间。如有任何帮助,将不胜感激。

【问题讨论】:

  • 这让我觉得这是一个可以通过递归更好地解决的问题。
  • 为什么不直接使用内置功能呢? echo json_encode(json_decode($json_data), JSON_PRETTY_PRINT); 如果你有原始数据,你可以跳过json_decode($json_data) 步骤。
  • @Nick - 因为我需要图像中的样式和数字。所以,JSON_PRETTY_PRINT 不提供这种能力。
  • @AlexBarker - 会对您的处理方法非常感兴趣。正在考虑同样的事情,但是,我一直在这个问题上碰壁。如果你有时间,会对一个简短的例子感兴趣吗?干杯 :) 如果需要示例,可以在此处下载 json 文件:dropbox.com/s/59bnd6h3nkacjcd/eventlog-json.json?dl=0
  • @SolomonClosson 你有原始数据,还是只有 JSON?

标签: php json pretty-print


【解决方案1】:

你为什么要手动解析 JSON?该代码将非常难以推理和维护,尤其是当您稍后在几乎不可避免地出现错误时返回它时。

与其采取困难的方法,不如考虑执行以下操作:
1. 重新格式化 JSON,使其适合您的需求。例如,在这种情况下,您更愿意将对象的右括号和结束括号保持在同一行,而不是在不同的行上。
2. 将已经格式化的 JSON 拆分为单独的行。
3. 将 JSON 的各行包装在 HTML 中。
4. 重新加入这些行以获得最终的 HTML。

function prettyWrapJson($json_data, $line_numbers = true) {
    // Ensure that our JSON is in pretty format.
    $json_data = json_encode(json_decode($json_data, true), JSON_PRETTY_PRINT);

    // Modify the formatting so that adjacent closing and opening curly braces are on the same line.
    // Note: we can add a similar line if we want to do the same for square brackets.
    $json_data = preg_replace('/},\n +{/s', '},{', $json_data);

    $line_number = 1;

    // Coerce a boolean value.
    $line_numbers = !empty($line_numbers);

    // Split into an array of separate lines.
    $json_lines = explode("\n", $json_data);

    // Wrap the individual lines.
    $json_lines = array_map(function($json_line) use ($line_numbers, &$line_number) {
        // Check if this line contains a property name.
        if(preg_match('/^( +"[^"]+"):/', $json_line, $matches)) {
            // Similar result to explode(':', $json_line), but safer since the colon character may exist somewhere else in the line.
            $parts = array($matches[1], substr($json_line, strlen($matches[1]) + 1));

            // Wrap the property in a span, but keep the spaces outside of it.
            $parts[0] = preg_replace('/^( +)/', '$1<span class="json-property">', $parts[0]) . '</span>';

            // We only want to wrap the other part of the string if it's a value, not an opening brace.
            if(strpos($parts[1], '{') === false && strpos($parts[1], '[') === false) {
                // Similarly, wrap the value in a span, but keep the spaces outside of it.
                $parts[1] = preg_replace('/^( +)/', '$1<span class="json-value">', $parts[1]) . '</span>';
            }

            // Re-join the string parts with the colon we stripped out earlier.
            $json_line = implode(':', $parts);
        }

        // Finally, we can wrap the line with a line number div if needed.
        if($line_numbers) {
            $json_line = '<div class="line" data-line-number="' . ($line_number++) . '">' . $json_line . '</div>';
        }

        return $json_line;
    }, $json_lines);

    // Re-join the lines and return the result.
    return implode("\n", $json_lines);
}

您可能需要稍微修改一下以使其格式完全符合您的喜好,但这对您来说应该更容易使用。

【讨论】:

  • 天哪,谢谢,只需将函数内的最后一行更改为implode(empty($line_numbers) ? "\n" : "", $json_lines);,这正是我所需要的。非常感谢!
  • 刚刚注意到末尾的逗号在&lt;span class="json-value"&gt; 标签内,有没有办法把逗号放在这个标签之外?
  • 没关系,用这段代码就知道了:if(strpos($parts[1], '{') === false &amp;&amp; strpos($parts[1], '[') === false) { $has_comma = substr($parts[1], -1) == ','; $parts[1] = preg_replace('/^( +)/', '$1&lt;span class="json-value"&gt;', ($has_comma) ? substr($parts[1], 0, -1) : $parts[1]) . '&lt;/span&gt;' . ($has_comma ? ',' : ''); } 再次感谢!
  • @SolomonClosson 没问题!老实说,即使这个解决方案也不是完美的——如果属性名称中的任何地方都包含转义的双引号,或者属性的值在文本中包含大括号或方括号,那么逻辑将失败。可以在这里进行更好的验证。更好的办法是将 JSON 解码为一个数据数组并递归遍历它,因为这样可以完全避免这个问题并且更加健壮。无论如何,请注意这是一个快速而肮脏的解决方案,具有所有限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-02
  • 2014-06-29
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
相关资源
最近更新 更多