Php 如何处理两次编码的JSON?

Php 如何处理两次编码的JSON?,php,json,Php,Json,我有以下两组需要解码的代码 $test = '{ "username":"sophia", "event":{ "failure":"unreset", "answers":{ "question1":"{\"answer\":\"{\\\"pass\\\":true,\\\"mark\\\":9,\\\"totalmark\\\":9,\\\"value\\\":\\\"get full attention|establ

我有以下两组需要解码的代码

$test = 
'{
    "username":"sophia",
    "event":{
        "failure":"unreset",
        "answers":{
            "question1":"{\"answer\":\"{\\\"pass\\\":true,\\\"mark\\\":9,\\\"totalmark\\\":9,\\\"value\\\":\\\"get full attention|establish classroom rules|teach key words & concepts|use visual aids|demonstrate|check understanding|introduce point system|give handouts|play\\\"}\",\"state\":\"{\\\"result\\\":{\\\"pass\\\":true,\\\"mark\\\":9,\\\"totalmark\\\":9,\\\"value\\\":\\\"get full attention|establish classroom rules|teach key words & concepts|use visual aids|demonstrate|check understanding|introduce point system|give handouts|play\\\"}}\"}"
        }
    },
     "event_source":"server"
}';
对于第一个,我根本无法解码它,尽管它是有效的。“问题1”部分似乎被编码了两次,我不知道这是怎么回事

$test = 
'{
    "username":"lon",
    "event":{
        "saved_response":"{\"parts\": [{\"text\": \"Passion for teaching means loving your job. Doing with all your heart. Teachers who are passionate can inspire pupils to love learning. Passionate teachers create an effective learning environment and increase learning potential of\\nstudents.\"}]}"
    },
    "event_source":"server"
}';

$jarray = json_decode($test, true);
$jevent = json_decode($jarray['event']['saved_response'], true);
对于第二个,我可以解码一次,但是
var\u dump($jevent)
的输出为空

有谁能向我解释一下为什么会出现这两个错误?我已经检查过了,我现在真的很困惑。
谢谢。

您必须从第二个json中删除新行

试试这个:

trim(preg_replace('/\s+/','.$jarray['event']['saved_response'])
-多个空格和换行符替换为单个空格

$test = 
'{
    "username":"lon",
    "event":{
        "saved_response":"{\"parts\": [{\"text\": \"Passion for teaching means loving your job. Doing with all your heart. Teachers who are passionate can inspire pupils to love learning. Passionate teachers create an effective learning environment and increase learning potential of\\nstudents.\"}]}"
    },
    "event_source":"server"
}';

$jarray = json_decode($test, true);
$jevent = json_decode( trim(preg_replace('/\s+/', ' ',$jarray['event']['saved_response'])), true);
var_dump($jarray);
var_dump($jevent);

作为替代方案,您可以双重转义:

$test = 
'{
    "username":"lon",
    "event":{
        "saved_response":"{\\"parts\\": [{\\"text\\": \\"Passion for teaching means loving your job. Doing with all your heart. Teachers who are passionate can inspire pupils to love learning. Passionate teachers create an effective learning environment and increase learning potential of\\\\nstudents.\\"}]}"
    },
    "event_source":"server"
}';

$jarray = json_decode($test, true);
$jevent = json_decode( $jarray['event']['saved_response'], true);
var_dump($jarray);
var_dump($jevent);


这将解码您断开的json字符串

$test = 
'{
    "username":"lon",
    "event":{
        "saved_response":"{\"parts\": [{\"text\": \"Passion for teaching means loving your job. Doing with all your heart. Teachers who are passionate can inspire pupils to love learning. Passionate teachers create an effective learning environment and increase learning potential of\\nstudents.\"}]}"
    },
    "event_source":"server"
}';

var_dump(json_decode(preg_replace('/[\x00-\x1F\x80-\xFF]/', '', json_decode($test, true)['event']['saved_response']), true)['parts'][0]['text']);

问题中的
$test
字符串不是您试图解析的数据的准确反映。您说过您从日志中复制并粘贴了它,但当您将包含反斜杠的文本粘贴到字符串文字中时,这些反斜杠不再是反斜杠,而是转义字符。你必须用另一个反斜杠来逃避它们。也就是说,如果文本中有
testing\foo
,并将其放入字符串文本中,则需要复制该反斜杠,使该文本创建一个包含相同文本的字符串:
'testing\\foo'

因此,为了准确反映从日志中复制的文本,
$test
文本应为:

$test = 
'{
    "username":"sophia",
    "event":{
        "failure":"unreset",
        "answers":{
            "question1":"{\\"answer\\":\\"{\\\\\\"pass\\\\\\":true,\\\\\\"mark\\\\\\":9,\\\\\\"totalmark\\\\\\":9,\\\\\\"value\\\\\\":\\\\\\"get full attention|establish classroom rules|teach key words & concepts|use visual aids|demonstrate|check understanding|introduce point system|give handouts|play\\\\\\"}\\",\\"state\\":\\"{\\\\\\"result\\\\\\":{\\\\\\"pass\\\\\\":true,\\\\\\"mark\\\\\\":9,\\\\\\"totalmark\\\\\\":9,\\\\\\"value\\\\\\":\\\\\\"get full attention|establish classroom rules|teach key words & concepts|use visual aids|demonstrate|check understanding|introduce point system|give handouts|play\\\\\\"}}\\"}"
        }
    },
     "event_source":"server"
}';
正如你所说,
问题1
是双重编码的。更糟糕的是,当您取消对它进行编码时,您会发现它具有名为
answer
state
的属性,这些属性是双重编码的

要取消所有代码的编码,您必须首先取消主位的编码,然后取消问题1的编码,然后取消其回答和状态的编码:

$obj = json_decode($test);
$obj->event->answers->question1 = json_decode($obj->event->answers->question1);
$obj->event->answers->question1->answer = json_decode($obj->event->answers->question1->answer);
$obj->event->answers->question1->state = json_decode($obj->event->answers->question1->state);
如果在转储到日志中的文本上执行此操作,它将起作用。结果(来自
var\u dump
)是:

对象(标准类)#1(3){ [“用户名”]=> 弦(6)“索菲亚” [“事件”]=> 对象(标准类)#2(2){ [“失败”]=> 字符串(7)“取消设置” [“答案”]=> 对象(标准类)#3(1){ [“问题1”]=> 对象(标准类)#4(2){ [“回答”]=> 对象(标准类)#5(4){ [“通过”]=> 布尔(真) [“标记”]=> 内部(9) [“totalmark”]=> 内部(9) [“值”]=> string(161)“全神贯注|制定课堂规则|教授关键词和概念|使用视觉教具|演示|检查理解|介绍评分系统|分发讲义|游戏” } [“状态”]=> 对象(标准类)#6(1){ [“结果”]=> 对象(标准类)#7(4){ [“通过”]=> 布尔(真) [“标记”]=> 内部(9) [“totalmark”]=> 内部(9) [“值”]=> string(161)“全神贯注|制定课堂规则|教授关键词和概念|使用视觉教具|演示|检查理解|介绍评分系统|分发讲义|游戏” } } } } } [“事件源”]=> 字符串(6)“服务器” }

实际上,这两个版本都已成功解码,嵌套的JSON部分也已正确解码。顺便说一句,如果您可以控制JSON的创建,您应该防止JSON数据被重新编码为另一个JSONI使用的一部分,并得到一个错误:“控制字符错误,可能编码不正确”。您的
$test
字符串导致JSON无效。但如果将其作为文本(例如,从文件或网络操作中读取),则它是有效的JSON。您在哪里以及如何接收此字符串?(区别在于反斜杠:您需要在
$test
字符串文字中转义它们。)@CassieLiu-字符串文字中的反斜杠转义下一个字符。如果从日志中获取包含反斜杠的文本并将其粘贴到
字符之间,则不会创建包含该文本的字符串。此文本:
testing\fun
中有一个反斜杠。如果将其粘贴到字符串文本中(
'testing\fun'
),则生成的字符串中没有反斜杠(由于转义序列
\f
,因此其中有一个formfeed)。要获取文本并将其转储为字符串文本,必须复制所有斜杠。文本
testing\fun
成为字符串文本
'testing\\fun'
@CassieLiu-如果将JSON粘贴到字符串文本中,是的,可以;如果您从文件或网络套接字等读取JSON,则不会。JSON仍然很奇怪,但它可以解析<代码>问题1是双重编码的,正如您所指出的,但更糟糕的是,其中的两个属性(
答案
状态
)也是双重编码的(总共是四倍编码)。但是如果新行是未指定的,需要保留在字符串中呢?他的json无效。“在这种情况下,他必须摆脱那条新路线。”安德烈鲁普利萨感谢你的努力!我只是想知道有什么办法可以保留新行字符? object(stdClass)#1 (3) { ["username"]=> string(6) "sophia" ["event"]=> object(stdClass)#2 (2) { ["failure"]=> string(7) "unreset" ["answers"]=> object(stdClass)#3 (1) { ["question1"]=> object(stdClass)#4 (2) { ["answer"]=> object(stdClass)#5 (4) { ["pass"]=> bool(true) ["mark"]=> int(9) ["totalmark"]=> int(9) ["value"]=> string(161) "get full attention|establish classroom rules|teach key words & concepts|use visual aids|demonstrate|check understanding|introduce point system|give handouts|play" } ["state"]=> object(stdClass)#6 (1) { ["result"]=> object(stdClass)#7 (4) { ["pass"]=> bool(true) ["mark"]=> int(9) ["totalmark"]=> int(9) ["value"]=> string(161) "get full attention|establish classroom rules|teach key words & concepts|use visual aids|demonstrate|check understanding|introduce point system|give handouts|play" } } } } } ["event_source"]=> string(6) "server" }