【问题标题】:JSON decode/encode loses newlines / file structure?JSON解码/编码丢失换行符/文件结构?
【发布时间】:2012-11-15 11:01:26
【问题描述】:

此 php 脚本向其中一个 JSON 对象(数组)添加一个元素。

#!/usr/bin/php
<?php

$filename = 'composer.json';
$obj = json_decode(file_get_contents($filename, true));

if (null === $obj) {
   throw new Exception(json_last_error()); // this will just be an error code
}

$obj->require = (object) array_merge((array) $obj->require, array('friendsofsymfony/user-bundle' => "*"));

file_put_contents(
    $filename,
    json_encode($obj)
);

问题是,它弄乱了文件格式。

在使用脚本之前,我正在编辑的文件如下所示:

{
    "name": "symfony/framework-standard-edition",
    "description": "The \"Symfony Standard Edition\" distribution",
    "autoload": {
        "psr-0": { "": "src/" }
    },
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "2.1.*",
        "doctrine/orm": ">=2.2.3,<2.4-dev",
        "doctrine/doctrine-bundle": "1.0.*",
        "twig/extensions": "1.0.*",
        "symfony/assetic-bundle": "2.1.*",
        "symfony/swiftmailer-bundle": "2.1.*",
        "symfony/monolog-bundle": "2.1.*",
        "sensio/distribution-bundle": "2.1.*",
        "sensio/framework-extra-bundle": "2.1.*",
        "sensio/generator-bundle": "2.1.*",
        "jms/security-extra-bundle": "1.2.*",
        "jms/di-extra-bundle": "1.1.*"
    },
    "scripts": {
        "post-install-cmd": [
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
        ],
        "post-update-cmd": [
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
        ]
    },
    "minimum-stability": "dev",
    "extra": {
        "symfony-app-dir": "app",
        "symfony-web-dir": "web"
    }
}

在我运行脚本之后;我明白了:

{"name":"symfony\/framework-standard-edition","description":"The \"Symfony Standard Edition\" distribution","autoload":{"psr-0":{"_empty_":"src\/"}},"require":{"php":">=5.3.3","symfony\/symfony":"2.1.*","doctrine\/orm":">=2.2.3,<2.4-dev","doctrine\/doctrine-bundle":"1.0.*","twig\/extensions":"1.0.*","symfony\/assetic-bundle":"2.1.*","symfony\/swiftmailer-bundle":"2.1.*","symfony\/monolog-bundle":"2.1.*","sensio\/distribution-bundle":"2.1.*","sensio\/framework-extra-bundle":"2.1.*","sensio\/generator-bundle":"2.1.*","jms\/security-extra-bundle":"1.2.*","jms\/di-extra-bundle":"1.1.*","friendsofsymfony\/user-bundle":"*"},"scripts":{"post-install-cmd":["Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap","Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache","Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets","Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"],"post-update-cmd":["Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap","Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache","Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets","Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"]},"minimum-stability":"dev","extra":{"symfony-app-dir":"app","symfony-web-dir":"web"}}

所有换行符等都丢失了。

我的 PHP 版本是 5.3.10,这意味着我不能使用具有“PRETTY_PRINT”选项的 PHP 5.4 进行编码。

有没有办法使用 json_encode(); 将我的文件结构保留在 PHP 5.3.10 中?

【问题讨论】:

    标签: php json


    【解决方案1】:

    使用print_r:

    $pretty_json = print_r(json_decode($arr, true), true);
    

    意识到你确实需要json文件,检查this function

    【讨论】:

    • 很抱歉说的很明显,但print_r() 不会生成 JSON。
    • 该功能似乎没问题,但似乎在引号内转义了斜线。这是正确的行为吗?
    • Jsonformatter 不接受 print_r 函数。如果可能的话,帮我解决这个问题stackoverflow.com/questions/41505176/…
    【解决方案2】:

    很遗憾没有。

    由于数据是供机器使用的,这应该不是主要问题 - 如果您想直观地检查它,有许多工具会根据上下文自动为您进行漂亮的打印。

    【讨论】:

    • 是否有一个 CLI/PHP 工具可以很好地格式化 json 文件?添加元素后,我可以在我的文件上运行该命令。
    【解决方案3】:

    为什么格式很重要?这肯定是为了让程序/进程使用,消除对人类可读性的需求?

    我有一个方便的谷歌浏览器扩展来查看 json 提要:

    https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa

    【讨论】:

      【解决方案4】:

      使用了Denis Ermolin提供的function,并添加了str_replace():

      <?php
      
      $filename = 'composer.json';
      $obj = json_decode(file_get_contents($filename, true));
      
      if (null === $obj) {
         throw new Exception(json_last_error()); // this will just be an error code
      }
      
      $obj->require = (object) array_merge((array) $obj->require, array('friendsofsymfony/user-bundle' => "*"));
      
      file_put_contents($filename,pretty_json(json_encode($obj)));
      
      function pretty_json($json) {
          $result      = '';
          $pos         = 0;
          $strLen      = strlen($json);
          $indentStr   = '  ';
          $newLine     = "\n";
          $prevChar    = '';
          $outOfQuotes = true;
          for ($i=0; $i<=$strLen; $i++) {
              // Grab the next character in the string.
              $char = substr($json, $i, 1);
              // Are we inside a quoted string?
              if ($char == '"' && $prevChar != '\\') {
                  $outOfQuotes = !$outOfQuotes;
              // If this character is the end of an element, 
              // output a new line and indent the next line.
              } else if(($char == '}' || $char == ']') && $outOfQuotes) {
                  $result .= $newLine;
                  $pos --;
                  for ($j=0; $j<$pos; $j++) {
                      $result .= $indentStr;
                  }
              }
              // Add the character to the result string.
              $result .= $char;
              // If the last character was the beginning of an element, 
              // output a new line and indent the next line.
              if (($char == ',' || $char == '{' || $char == '[') && $outOfQuotes) {
                  $result .= $newLine;
                  if ($char == '{' || $char == '[') {
                      $pos ++;
                  }
                  for ($j = 0; $j < $pos; $j++) {
                      $result .= $indentStr;
                  }
              }
              $prevChar = $char;
          }
          $result = str_replace("\\/", "/", $result);
          return $result;
      }
      ?>
      

      或者只是更新到 PHP 5.4 以使用 PRETTY_PRINT ...

      【讨论】:

        猜你喜欢
        • 2011-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多