【问题标题】:PHP: convert javascript object string to php arrayPHP:将javascript对象字符串转换为php数组
【发布时间】:2019-04-16 22:44:49
【问题描述】:

我通过 phpQuery 获取一页 html 源代码,然后通过 php regex 从 head 中的脚本标记获取以下字符串代码:

var BASE_DATA = {
userInfo: {
  id: 0,
  userName: 'no-needed',
  avatarUrl: 'no-needed',
  isPgc: false,
  isOwner: false
},
headerInfo: {
  id: 0,
  isPgc: false,
  userName: 'no-needed',
  avatarUrl: 'no-needed',
  isHomePage: false,
  crumbTag: 'no-needed',
  hasBar: true
},
articleInfo: 
{
  title: 'needed',
  content: 'needed',
  groupId: 'needed',
  itemId: 'needed',
  type: 1,
  subInfo: {
    isOriginal: false,
    source: 'needed',
    time: 'needed'
  },
  tagInfo: {
    tags: [{"name":"no-needed 1"},{"name":"no-needed 2"},{"name":"no-needed 3"}],
    groupId: 'no-needed',
    itemId: 'no-needed',
    repin: 0,
  },
  has_extern_link: 0,
  coverImg: 'no-needed'
},
commentInfo:
{
  groupId: 'no-needed',
  itemId: 'no-needed',
  comments_count: 151,
  ban_comment: 0
},};

我想把这个字符串转换成php数组,比如:

$base_data = array(
'articleInfo' => array(
    'title' => 'needed',
    'content' => 'needed',
    'groupId' => 'needed',
    'itemId' => 'needed',
    'subInfo' => array(
        'source' => 'needed',
        'time' => 'needed',
    ),
));

$base_data = array(
'title' => 'needed',
'content' => 'needed',
'groupId' => 'needed',
'itemId' => 'needed',
'subInfo' => array(
    'source' => 'needed',
    'time' => 'needed',
),);

我已经尝试了很多方法,例如:json_decode,通过php regex和函数preg_match_all从大括号中获取内容。但是它们都运行得不好。

我尝试了两种方法:

第一种方式:

$json = str_ireplace(array('var BASE_DATA =', '};'), array('', '}'), $js);
json_decode($json, true);

第二种方式:

preg_match_all('/\{([^}]+)\}/', $js, $matches);
print_r($matches[1]);

preg_match_all('/articleInfo:\s*\{([^}]+)\}/', $script_text, $matches);
print_r($matches[1][0]);

似乎快要结束了,但看起来还是不太好,我必须在 articleInfo 部分解析字符串....这就是我发布这篇文章的原因。

我什至想用 V8 JavaScript 引擎,但是.....

请问有谁知道完成它的更好方法吗?

【问题讨论】:

  • 如果源字符串包含 var BASE_DATA = 部分,则在将其剥离之前,您将无法对其进行 json_decode。最后的逗号也是一个问题,它可能会或可能不会抱怨最后一个分号。在这方面不确定 json_decode 有多宽容。
  • 是的,我已经发现了这个问题,所以我已经尝试过 str_ireplace(array('var BASE_DATA =', '};'), array('', '}'), $js) ;但我确实知道接下来我应该做什么。实际上,我也尝试过: preg_match_all('/\{([^}]+)\}/', $js, $matches);它似乎接近完成,但看起来仍然不太好,我必须在 articleInfo 部分解析字符串....这就是我发布这篇文章的原因。
  • “我已经尝试了很多方法”确实告诉...
  • @miken32 我编辑了,请检查

标签: javascript php regex parsing


【解决方案1】:

我不得不重新格式化无效的 JSON(检查 https://jsonlint.com/)。

我自愿使用了多个 str_replace(),以便您更好地理解该过程,但是您可以通过在同一个 str_replace() 中同时进行多个替换来优化下面的代码。

这行得通:

<?php

$to_decode = "var BASE_DATA = {
userInfo: {
  id: 0,
  userName: 'no-needed',
  avatarUrl: 'no-needed',
  isPgc: false,
  isOwner: false
},
headerInfo: {
  id: 0,
  isPgc: false,
  userName: 'no-needed',
  avatarUrl: 'no-needed',
  isHomePage: false,
  crumbTag: 'no-needed',
  hasBar: true
},
articleInfo: 
{
  title: 'needed',
  content: 'needed',
  groupId: 'needed',
  itemId: 'needed',
  type: 1,
  subInfo: {
    isOriginal: false,
    source: 'needed',
    time: 'needed'
  },
  tagInfo: {
    tags: [{\"name\":\"no-needed 1\"},{\"name\":\"no-needed 2\"},{\"name\":\"no-needed 3\"}],
    groupId: 'no-needed',
    itemId: 'no-needed',
    repin: 0,
  },
  has_extern_link: 0,
  coverImg: 'no-needed'
},
commentInfo:
{
  groupId: 'no-needed',
  itemId: 'no-needed',
  comments_count: 151,
  ban_comment: 0
},};";

/* Clean JSON and encapsulate in brackets */
$to_decode = str_replace('var BASE_DATA = {', '', $to_decode);
$to_decode = '{'.substr($to_decode, 0, -3).'}';

/* Remove spaces, tabs, new lines, etc. */
$to_decode = str_replace(' ', '', $to_decode);
$to_decode = str_replace("\n", '', $to_decode);
$to_decode = str_replace("\t", '', $to_decode);
$to_decode = str_replace("\r", '', $to_decode);

/* Encapsulate keys with quotes */
$to_decode = preg_replace('/([a-z_]+)\:/ui', '"{$1}":', $to_decode);
$to_decode = str_replace('"{', '"', $to_decode);
$to_decode = str_replace('}"', '"', $to_decode);
$to_decode = str_replace('\'', '"', $to_decode);

/* Remove unecessary trailing commas */
$to_decode = str_replace(',}', '}', $to_decode);

echo '<pre>';
var_dump(json_decode($to_decode));

使用 print_r 的结果:

(为了清楚起见,我添加了真/假,否则这些将仅使用 var_dump() 显示)

stdClass Object
(
    [userInfo] => stdClass Object
        (
            [id] => 0
            [userName] => no-needed
            [avatarUrl] => no-needed
            [isPgc] => false
            [isOwner] => false
        )

    [headerInfo] => stdClass Object
        (
            [id] => 0
            [isPgc] => false
            [userName] => no-needed
            [avatarUrl] => no-needed
            [isHomePage] => false
            [crumbTag] => no-needed
            [hasBar] => true
        )

    [articleInfo] => stdClass Object
        (
            [title] => needed
            [content] => needed
            [groupId] => needed
            [itemId] => needed
            [type] => 1
            [subInfo] => stdClass Object
                (
                    [isOriginal] => false
                    [source] => needed
                    [time] => needed
                )

            [tagInfo] => stdClass Object
                (
                    [tags] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [name] => no-needed1
                                )

                            [1] => stdClass Object
                                (
                                    [name] => no-needed2
                                )

                            [2] => stdClass Object
                                (
                                    [name] => no-needed3
                                )

                        )

                    [groupId] => no-needed
                    [itemId] => no-needed
                    [repin] => 0
                )

            [has_extern_link] => 0
            [coverImg] => no-needed
        )

    [commentInfo] => stdClass Object
        (
            [groupId] => no-needed
            [itemId] => no-needed
            [comments_count] => 151
            [ban_comment] => 0
        )

)

【讨论】:

    【解决方案2】:

    感谢@Bruno Leveque 的想法。

    我像下面这样编辑了您的代码,使其运行良好:

    1. 我把$to_decode = str_replace(' ', '', $to_decode);改成了$to_decode = preg_replace('/[\n| |\s]{2,}/',' ',$to_decode);,意思是所有的1+空格都会改成1空格。因为有时我们需要空间,例如: content: '

    2. 我在你的评论代码/* Encapsulate keys with quotes */前加了$to_decode = str_replace("'", '"', $to_decode);

    3. $to_decode = preg_replace('/([a-z_]+)\:/ui', '"{$1}":', $to_decode); 更改为$to_decode = preg_replace('/([a-z_]+)\: /ui', '"$1":', $to_decode);(多了一个空格);并评论了//$to_decode = str_replace('"{', '"', $to_decode);//$to_decode = str_replace('}"', '"', $to_decode);

    4. 又添加了一个代码:$to_decode = str_replace(", }", '}', $to_decode);

    所以我的最终代码是:

    因为@Bruno Leveque 不知道“需要”和“不需要”的确切内容,所以谢谢你的想法。

    似乎没有完美的方法....

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 1970-01-01
      相关资源
      最近更新 更多