PHP json_decode -引号格式[已关闭]

yquaqz18  于 4个月前  发布在  PHP
关注(0)|答案(1)|浏览(48)

已关闭。此问题需要details or clarity。目前不接受回答。
**要改进此问题吗?**通过editing this post添加详细信息并阐明问题。

20天前关闭。
Improve this question
我试图用json_decode($str, false)解码一个json字符串。但格式不正确。

{mDetailedState:CONNECTED,mExtraInfo:3gnet,mIsAvailable:true}

字符串
我想这是因为报价的问题。
对于key,我可以通过(reference)将引号加回去
$json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json);
结果将是

{"mDetailedState":CONNECTED,"mExtraInfo":3gnet,"mIsAvailable":true}


但是,这个函数不能将引号添加回值。我不熟悉正则表达式。为了将引号添加回值,我可以参考任何参考,或者任何想法,我可以更容易地将JSON转换为数组?谢谢

olhwl3o2

olhwl3o21#

当我找到一个“解决方案”的时候,你确实大大简化了你最初的问题,你的初始有效载荷包含方括号和等号,没有引号,整个语法非常脆弱,我仍然尽我所能用几个假设来分析数据:
1.方括号和花括号被假设为相同的,并假设开始一个新的关联数组。
1.等号和冒号被假设为相同的,并被假设为表示关联数组的键和值。
1.值后面的方括号和花括号被认为是值的一部分,需要右方括号或花括号。

$data = '{mDetailedState:CONNECTED,mExtraInfo:3gnet,mIsAvailable:true,mIsFailover:false,mIsMetered:true,mIsRoaming:false,mNetworkType:0,mReason:connected,mState:CONNECTED,mSubtype:13,mSubtypeName:LTE,mTypeName:MOBILE,CREATOR:android.net.NetworkInfo$1@41bcdce,stateMap:{IDLE=DISCONNECTED,SCANNING=DISCONNECTED,CONNECTING=CONNECTING,AUTHENTICATING=CONNECTING,
OBTAINING_IPADDR=CONNECTING,CONNECTED=CONNECTED,SUSPENDED=SUSPENDED,DISCONNECTING=DISCONNECTING,DISCONNECTED=DISCONNECTED,FAILED=DISCONNECTED,BLOCKED=DISCONNECTED,VERIFYING_POOR_LINK=CONNECTING,CAPTIVE_PORTAL_CHECK=CONNECTING},describeContents:0,getDetailedState:CONNECTED,getExtraInfo:3gnet,getReason:connected,getState:CONNECTED,getSubtype:13,getSubtypeName:LTE,getType:0,getTypeName:MOBILE,isAvailable:true,isConnected:true,isConnectedOrConnecting:true,isFailover:false,isMetered:true,isRoaming:false,toString:[type:MOBILE[LTE],state:CONNECTED/CONNECTED,reason:connected,extra:3gnet,failover:false,available:true,roaming:false,metered:true]}';

$object = null;
$state = [];
$accumulator = '';
$pointer = [];

function set( &$object, $pointer, $value ) {
    if ( empty( $pointer ) ) {
        $object = $value;
        return;
    }

    $point = &$object;
    foreach ( array_slice( $pointer, 0, -1 ) as $key ) {
        $point = &$object[ $key ];
    }
    $point[ end( $pointer ) ] = $value;
}

foreach ( str_split( $data ) as $c ) {
    switch ( $c ):
        case '{':
        case '[':
            if ( end( $state ) === 'new_value' ) {
                if ( $accumulator ) {
                    $accumulator .= $c;
                    array_push( $state, 'new_array' );
                } else {
                    array_pop( $state );
                }
                break;
            }

            set( $object, $pointer, [] );
            array_push( $state, 'new_object' );
            break;
        case '}':
        case ']':
            if ( end( $state ) === 'new_array' ) {
                $accumulator .= $c;
                array_pop( $state );
            }

            if ( end( $state ) === 'new_value' ) {
                set( $object, $pointer, $accumulator );
                $accumulator = '';
                array_pop( $pointer );
                array_pop( $state );
            }

            if ( end( $state ) === 'new_object' ) {
                array_pop( $pointer );
                array_pop( $state );
            }

            break;
        case ':':
        case '=':
            array_push( $pointer, $accumulator );
            $accumulator = '';
            set( $object, $pointer, [] );
            array_push( $state, 'new_value' );
            break;
        case ',':
            if ( end( $state ) === 'new_value' ) {
                set( $object, $pointer, $accumulator );
                $accumulator = '';
                array_pop( $state );
                array_pop( $pointer );
            }
            break;
        default:
            $accumulator .= $c;
            break;
    endswitch;
}

var_dump( $object );

个字符
虽然这演示了一个工作示例,但数据最终可能会包含一些边缘情况,例如值中的额外逗号等。这个问题无法可靠地解决,即使使用正则表达式进行清理(替换all = to:等)也很难解决。当您遇到边缘情况时,您需要进一步卷积状态机并添加错误检查,跟踪和单元测试。
正如其他人所说的,从设备发送正确结构化/序列化的数据。如果没有正式的语法,这可以在假设上工作,相信我,这将打破,解析器将需要一遍又一遍地修复。但是如果你需要,上面的代码可以让你开始14天。

相关问题