วิธีที่เร็วที่สุดในการตรวจสอบว่าสตริงคือ JSON ใน PHP?


385

ฉันต้องการวิธีการตรวจสอบอย่างรวดเร็วจริงๆว่าสตริงเป็น JSON หรือไม่ ฉันรู้สึกว่านี่ไม่ใช่วิธีที่ดีที่สุด:

function isJson($string) {
    return ((is_string($string) &&
            (is_object(json_decode($string)) ||
            is_array(json_decode($string))))) ? true : false;
}

ผู้ที่ชื่นชอบการปฏิบัติงานที่นั่นต้องการปรับปรุงวิธีนี้หรือไม่?


3
พิจารณาใช้เพียงjson_decodeครั้งเดียว ... json_decodeนอกจากนี้ยังตรวจสอบการป้อนข้อมูลและการกลับมาของค่า

5
ดังนั้นคำตอบข้อใด?
Farid Rn

8
สวิตช์ที่ประกอบไปด้วยที่นี่ซ้ำซ้อน คำสั่งของคุณประเมินว่าเป็นบูลีนแล้ว
ฉันปล้ำหมีหนึ่งครั้ง


ยอมรับคำตอบของ Lewis Donovan ... มันใช้ได้ดี
Poonam Bhatt

คำตอบ:


574
function isJson($string) {
 json_decode($string);
 return (json_last_error() == JSON_ERROR_NONE);
}

19
ดูเหมือนว่าทุกคนจะรักคำตอบนี้ คำอธิบายใด ๆ ทำไม?
Kirk Ouimet

8
ฉันเชื่อว่า PHP 5.3> จำเป็นสำหรับการใช้งานฟังก์ชั่น json_last_error
Chris Harrison

97
การตรวจสอบตัวอักษรตัวแรกของสตริงสำหรับ{, [หรือสัญลักษณ์แรกของตัวอักษรอื่น ๆ ที่อาจเกิดขึ้นมากสามารถเพิ่มความเร็วในการนี้ขึ้นเมื่อหลายสายที่เข้ามาคาดว่าจะไม่ใช่ JSON
Oleg V. Volkov

20
$ phone = '021234567'; var_dump (isJson ($ โทรศัพท์)); คืนจริงไม่! มันควรกลับเท็จ
ve

23
ระวังฟังก์ชั่นนี้จะคืนค่าเป็นจริงสำหรับหมายเลขใด ๆ ด้วยไม่ว่าคุณจะระบุเป็นสตริงหรือจำนวนจริง 6.5 = true, '300' = true, 9 = trueเป็นต้นดังนั้นนี่อาจเป็นค่า JSON ที่ถูกต้อง แต่ฟังก์ชั่นอาจไม่ทำงานตามที่คุณคาดหวังหากคุณต้องการตรวจสอบเฉพาะสตริง JSON ที่ถูกต้องด้วย{}หรือ[];
BadHorsie

156

ตอบคำถาม

ฟังก์ชันjson_last_errorส่งคืนข้อผิดพลาดล่าสุดที่เกิดขึ้นระหว่างการเข้ารหัสและถอดรหัส JSON ดังนั้นวิธีที่เร็วที่สุดในการตรวจสอบ JSON ที่ถูกต้องคือ

// decode the JSON data
// set second parameter boolean TRUE for associative array output.
$result = json_decode($json);

if (json_last_error() === JSON_ERROR_NONE) {
    // JSON is valid
}

// OR this is equivalent

if (json_last_error() === 0) {
    // JSON is valid
}

โปรดทราบว่าjson_last_errorได้รับการสนับสนุนใน PHP> = 5.3.0 เท่านั้น

โปรแกรมเต็มรูปแบบเพื่อตรวจสอบข้อผิดพลาดที่แน่นอน

เป็นการดีที่จะทราบข้อผิดพลาดที่แน่นอนในระหว่างการพัฒนา นี่คือโปรแกรมเต็มรูปแบบเพื่อตรวจสอบข้อผิดพลาดที่แน่นอนขึ้นอยู่กับเอกสาร PHP

function json_validate($string)
{
    // decode the JSON data
    $result = json_decode($string);

    // switch and check possible JSON errors
    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            $error = ''; // JSON is valid // No error has occurred
            break;
        case JSON_ERROR_DEPTH:
            $error = 'The maximum stack depth has been exceeded.';
            break;
        case JSON_ERROR_STATE_MISMATCH:
            $error = 'Invalid or malformed JSON.';
            break;
        case JSON_ERROR_CTRL_CHAR:
            $error = 'Control character error, possibly incorrectly encoded.';
            break;
        case JSON_ERROR_SYNTAX:
            $error = 'Syntax error, malformed JSON.';
            break;
        // PHP >= 5.3.3
        case JSON_ERROR_UTF8:
            $error = 'Malformed UTF-8 characters, possibly incorrectly encoded.';
            break;
        // PHP >= 5.5.0
        case JSON_ERROR_RECURSION:
            $error = 'One or more recursive references in the value to be encoded.';
            break;
        // PHP >= 5.5.0
        case JSON_ERROR_INF_OR_NAN:
            $error = 'One or more NAN or INF values in the value to be encoded.';
            break;
        case JSON_ERROR_UNSUPPORTED_TYPE:
            $error = 'A value of a type that cannot be encoded was given.';
            break;
        default:
            $error = 'Unknown JSON error occured.';
            break;
    }

    if ($error !== '') {
        // throw the Exception or exit // or whatever :)
        exit($error);
    }

    // everything is OK
    return $result;
}

การทดสอบด้วย JSON INPUT ที่ถูกต้อง

$json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
$output = json_validate($json);
print_r($output);

ผลลัพธ์ที่ถูกต้อง

Array
(
    [0] => stdClass Object
        (
            [user_id] => 13
            [username] => stack
        )

    [1] => stdClass Object
        (
            [user_id] => 14
            [username] => over
        )
)

การทดสอบด้วย JSON ที่ไม่ถูกต้อง

$json = '{background-color:yellow;color:#000;padding:10px;width:650px;}';
$output = json_validate($json);
print_r($output);

OUTPUT ไม่ถูกต้อง

Syntax error, malformed JSON.

หมายเหตุพิเศษสำหรับ (PHP> = 5.2 && PHP <5.3.0)

เนื่องจากjson_last_errorไม่รองรับใน PHP 5.2 คุณสามารถตรวจสอบว่าการเข้ารหัสหรือถอดรหัสคืนค่าบูลีนFALSEหรือไม่ นี่คือตัวอย่าง

// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
    // JSON is invalid
}

หวังว่านี่จะเป็นประโยชน์ Happy Coding!


ความแม่นยำน้อย: ถ้า json นี้ถูกต้อง แต่อันที่ถอดรหัสก่อนหน้านั้นไม่ถูกต้องรหัสของคุณจะทำงานได้อย่างถูกต้องเพราะ: " ส่งกลับข้อผิดพลาดล่าสุด (ถ้ามี) เกิดขึ้นในระหว่างการเข้ารหัส / ถอดรหัส JSON ล่าสุด "
Bruno

ขอบคุณ @Madan การตรวจสอบ "json_decode" แก้ไขให้ฉันว่าฉันใช้ PHP 7.0
Francis Rodrigues

แท้จริงแล้ว json_decode สามารถคืนค่าเท็จสำหรับเท็จตามตัวอักษรดังนั้นการตรวจสอบ((strlen($json) === 5) && ($json !== 'false'))ควรดำเนินการเพื่อหลีกเลี่ยงขอบนั้น?
MrMesees

@Bruno ถ้าถอดรหัสที่ผ่านมาทำงานโดยไม่มีข้อผิดพลาดแล้วผลตอบแทนjson_last_error JSON_ERROR_NONE
Andrea

81

สิ่งที่คุณต้องทำคือ ...

if (is_object(json_decode($MyJSONArray))) 
{ 
    ... do something ...
}

คำขอนี้ไม่จำเป็นต้องมีฟังก์ชั่นแยกจากกัน เพียงแค่ห่อ is_object รอบ json_decode และไปต่อ ดูเหมือนว่าวิธีนี้จะทำให้คนคิดมากเกินไป


@ RomanM.Kos เพียงเพื่อให้ชัดเจนถ้าอาร์เรย์เป็นอาร์เรย์ที่เรียบง่ายแล้วคุณต้องใช้is_arrayนอกเหนือจากis_objectนั้นมิฉะนั้นis_objectจะส่งคืนเท็จสำหรับอาร์เรย์ที่เรียบง่ายที่เข้ารหัสเป็น JSON ดังนั้น @ggutenberg นั้นถูกต้องในกรณีนี้ การส่งผ่านอาร์กิวเมนต์ที่แท้จริงเพื่อjson_decodeบังคับให้วัตถุถูกส่งคืนเป็นอาร์เรย์ ในทางทฤษฎีคุณสามารถบังคับให้ถอดรหัสเป็นอาร์เรย์และตรวจสอบis_arrayว่าควรจะทำงาน
userabuser

@userabuser ถ้าฉันใช้json_encode($array)กับ PHP array แบบเรียบง่ายแล้วjson_decode($str)ฉันจะได้รับ object แต่ไม่ใช่ array json_decode($str, true)กองกำลังที่จะแปลงเป็นอาร์เรย์ ทำไมสตริงที่ซับซ้อนในรหัสของคุณ? ตรวจสอบis_array(json_decode($str, true))และในภายหลังเมื่อคุณอ่านคุณจะเข้าใจว่าถอดรหัสต้องเป็นอาร์เรย์เท่านั้น คาดเดาได้ยากกว่ามากis_object(json_decode($MyJSONArray))"โอ้นี่ฉันกำลังตรวจสอบการถอดรหัสเป็นอาร์เรย์หรือไม่"
Roman M. Koss

@ RomanM.Kos ไม่มีที่ไม่ถูกต้องcodepad.viper-7.com/OFrtsq - ที่ผมกล่าวว่าคุณมักจะสามารถบังคับjson_decodeเพื่อกลับอาร์เรย์เพื่อช่วยให้คุณประหยัดตรวจหาวัตถุและอาเรย์ แต่ถ้าคุณทำไม่ได้และคุณjson_decodeสิ่งที่ เป็นอาเรย์ง่ายๆที่จะเริ่มต้นด้วยคุณจะได้รับอาเรย์คืนในการถอดรหัสไม่ใช่วัตถุ คุณต้องใช้JSON_FORCE_OBJECTถ้าคุณต้องการบังคับให้วัตถุเข้ารหัสหากผ่านอาร์เรย์อย่างง่าย
userabuser

11
downvote This request does not require a separate function evenสำหรับพูดว่า: พูดอย่างเคร่งครัดไม่ต้องใช้ฟังก์ชั่นแยกต่างหาก จุดของฟังก์ชั่นไม่ได้ทำให้โค้ดหลายบรรทัดดูเหมือนรหัสหนึ่งบรรทัด จุดประสงค์ของฟังก์ชั่นนี้คือการทำให้มาตรฐานกระบวนการตรวจสอบ JSON ทุกที่ในแอปพลิเคชันของคุณเพื่อให้โปรแกรมเมอร์ที่แตกต่างกัน (หรือโปรแกรมเมอร์คนเดียวกันตลอดเวลา) ไม่ใช้ขั้นตอนการตรวจสอบที่แตกต่างกัน
cartbeforehorse

71

การใช้ json_decodeเพื่อ "โพรบ" อาจไม่ใช่วิธีที่เร็วที่สุด ถ้ามันเป็นโครงสร้างที่ซ้อนกันอย่างลึกซึ้งการยกตัวอย่างอาร์เรย์ของวัตถุจำนวนมากเพื่อให้พวกมันทิ้งไปนั้นเป็นการสูญเสียความทรงจำและเวลา

ดังนั้นจึงอาจใช้งานได้เร็วขึ้นpreg_matchและRFC4627 regexเพื่อรับรองความถูกต้อง :

  // in JS:
  var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
         text.replace(/"(\\.|[^"\\])*"/g, '')));

เหมือนกันใน PHP:

  return !preg_match('/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/',
       preg_replace('/"(\\.|[^"\\\\])*"/', '', $json_string));

อย่างไรก็ตามผู้ที่ชื่นชอบการแสดงไม่พอที่จะรำคาญกับการวัดประสิทธิภาพที่นี่


11
ทำ regex แบบเรียกซ้ำให้สมบูรณ์เพื่อตรวจสอบ JSON ที่นี่: stackoverflow.com/questions/2583472/regex-to-validate-json/… - แต่ปรากฎว่า PHPs json_decodeนั้นเร็วกว่า regex PCRE เสมอ (แม้ว่ามันจะไม่เหมาะมากไม่มีการทดสอบสังเคราะห์พบและอาจจะทำงานแตกต่างกันใน Perl .. )
มาริโอ

3
@vee ใช่ขอบคุณสำหรับบันทึก แต่ให้มันไว้ที่นี่ [ไม่ถูกต้อง] ดังนั้นจึงไม่มีใครใช้มันในการผลิต
มาริโอ

1
@cartbeforehorse โอเคขอบคุณ ฉันคงหนีบริบทสุทธ์สำหรับ PHPs บริบทสตริงคู่ที่ยกมาแล้ว
มาริโอ

1
@cartbeforehorse มันไม่ได้ ตกแต่งเป็นส่วนใหญ่ มันเป็นเพียงแบ็คสแลชตัวอักษรที่ไม่ต้องการการหลบหนีซ้ำ เพราะ\r \n \tมันสมเหตุสมผลแล้วดังนั้น PHP ไม่ได้ทำการสอดแทรก แต่ให้ PCRE ตีความมัน (จำเป็นสำหรับ/xโหมดเท่านั้น) เหตุการณ์อื่น ๆ ไม่จำเป็นต้องใช้อย่างเคร่งครัด แต่ยังคง "แบ็กสแลชหนีออกมาเอง" ในบริบทสตริงของ PHP ทั้งหมด ดังนั้นเราสามารถพิจารณาได้อย่างแม่นยำยิ่งขึ้น
มาริโอ

4
@mario โอเคฉันเห็น ดังนั้นโดยทั่วไป PHP จะหนีแบ็กสแลชก่อนที่เอ็นจิน reg-exp จะเห็น เท่าที่เอ็นจิ้นการรีจิสเตอร์ exp เกี่ยวข้องมีแบ็กสแลชในสายอักขระครึ่งหนึ่งเท่าที่เราเห็น "เช่น reg-exp ก็ไม่ซับซ้อนพออยู่แล้ว"
cartbeforehorse

39

สิ่งนี้จะคืนค่าจริงถ้าสตริงของคุณแทนอาร์เรย์หรือวัตถุ json :

function isJson($str) {
    $json = json_decode($str);
    return $json && $str != $json;
}

มันปฏิเสธสตริง json ที่มีเพียงตัวเลขสตริงหรือบูลีนแม้ว่าสตริงเหล่านั้นจะเป็น json ที่ถูกต้องในทางเทคนิค

var_dump(isJson('{"a":5}')); // bool(true)
var_dump(isJson('[1,2,3]')); // bool(true)
var_dump(isJson('1')); // bool(false)
var_dump(isJson('1.5')); // bool(false)
var_dump(isJson('true')); // bool(false)
var_dump(isJson('false')); // bool(false)
var_dump(isJson('null')); // bool(false)
var_dump(isJson('hello')); // bool(false)
var_dump(isJson('')); // bool(false)

มันเป็นวิธีที่สั้นที่สุดที่ฉันสามารถทำได้


แทนที่จะเป็น var_dump คุณสามารถใส่ไว้ในกรณีทดสอบ PHPUnit ไม่งั้นฉันก็แปลกใจและดีใจที่รู้ว่ามันเป็นเรื่องจริง
MrMesees

3
ทำไมทุกคนถึงมีคำตอบที่ยืดยาวเช่นนี้เมื่อใช้งานได้ดี? ขอบคุณ
toddmo

1
เรียบง่ายน่ารัก! ไม่ได้ตรวจสอบ "วิธีที่เร็วที่สุด" หรือประสิทธิภาพที่ชาญฉลาด แต่สิ่งนี้แน่ใจว่าครอบคลุมทุกกรณีที่ฉันเคยตรวจสอบ นี่เป็นตัวอย่างคลาสสิกสำหรับสุภาษิตที่น่าอับอาย"อย่าใช้ค้อนขนาดใหญ่เพื่อแคร็ก" "ไม่ได้ใช้ค้อนขนาดใหญ่จะแตกถั่ว"จากมุมมองของโปรแกรมเมอร์มันจะดีกว่าเสมอเพื่อให้โค้ดง่ายสั้นและเข้าใจง่ายประสิทธิภาพเทียบกับความเรียบง่ายเป็นการถกเถียงกันเกินขอบเขตสำหรับเธรดนี้
Fr0zenFyr

นี่เป็นตรรกะที่เรียบร้อย แต่โปรดทราบว่ามันจะส่งกลับค่า false สำหรับอาร์เรย์ที่ว่างเปล่า ตัวอย่างเช่น:var_dump(isJson('[]')); // bool(false) . ตามเอกสารเกี่ยวกับ booleans นี่เป็นเพราะ PHP ประเมินอาร์เรย์ที่มีองค์ประกอบศูนย์เป็นเท็จ นี่คือการแก้ไขเล็กน้อยเพื่อปรับคำสั่งการส่งคืน; มันทำการเปรียบเทียบที่เหมือนกันกับเอาท์พุทถอดรหัสซึ่งจัดการกับกรณีนี้:return $json !== false && $str != $json;
j13k

@ j13k การเปรียบเทียบแบบเหมือนกันประเมินisJson('hello')เป็นจริงซึ่งไม่ถูกต้อง json การเปรียบเทียบแบบหลวมถูกเลือกโดยมีจุดประสงค์ที่นี่ ฉันไม่มีวิธีแก้ปัญหาอย่างรวดเร็วสำหรับอาเรย์ / วัตถุว่างเปล่ายกเว้นสิ่งที่น่าเกลียดreturn $json == '[]' || ...
Cyril

21

วิธีที่ง่ายและเร็วที่สุดที่ฉันใช้คือการติดตาม

$json_array = json_decode( $raw_json , true );

if( $json_array == NULL )   //check if it was invalid json string
    die ('Invalid');  // Invalid JSON error

 // you can execute some else condition over here in case of valid JSON

เป็นเพราะ json_decode ()ส่งคืนค่า NULL ถ้าสตริงที่ป้อนไม่ใช่ json หรือ json ที่ไม่ถูกต้อง


ฟังก์ชั่นง่าย ๆ ในการตรวจสอบ JSON

หากคุณต้องตรวจสอบ JSON ของคุณในหลาย ๆ ที่คุณสามารถใช้ฟังก์ชันต่อไปนี้ได้เสมอ

function is_valid_json( $raw_json ){
    return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}

ในฟังก์ชั่นด้านบนคุณจะได้รับผลตอบแทนจริงหากเป็น JSON ที่ถูกต้อง


3
json_decode('null') == NULLและnullเป็นค่า JSON ที่ถูกต้อง
zzzzBov

ฉันได้ทดสอบว่า 'โมฆะ' เป็น json ที่ถูกต้องที่json.parser.onlineแต่ดูเหมือนว่ามันไม่ถูกต้อง json และjson_decode ()เป็นฟังก์ชั่นหลักของ php เพื่อตรวจสอบความถูกต้องของ json ดังนั้นฉันสงสัยว่าจะได้ผลลัพธ์ที่ผิดพลาดในผลลัพธ์ของเรา
Mohammad Mursaleen

มากกว่าความไว้วางใจบางเว็บไซต์ที่ไม่ได้ยืนยัน, พิจารณาให้คำปรึกษาข้อมูลจำเพาะซึ่งไม่เห็นด้วย (หน้า 2) หรือลองใช้JSON.parse('null')คอนโซล dev ของคุณ
zzzzBov

19
function is_json($str){ 
    return json_decode($str) != null;
}

http://tr.php.net/manual/th/function.json-decode.phpค่าส่งคืนเป็นโมฆะเมื่อตรวจพบการเข้ารหัสที่ไม่ถูกต้อง


4
มันจะส่งคืนค่า null ไม่ถูกต้องสำหรับ "null" (ซึ่งไม่ถูกต้อง JSON แต่อาจเป็น "ถูกต้อง" ทั้งหมดไปยัง json_decode) ไปคิด

ผมคิดว่า sould นี้เป็น: หรือมิฉะนั้นฟังก์ชั่นควรจะเรียกว่าjson_decode($str)!=null; is_not_json
Yoshi

ฟังก์ชั่นนั้นจะเปลี่ยนชื่อได้ดีกว่า "เป็นสิ่งอื่นที่ไม่ใช่ JSON"!
lonesomeday


โปรดทราบด้วยวิธีนี้is_json('false')และis_json('[]')จะกลับมาfalseเนื่องจากไม่ได้ตรวจสอบประเภท $str === null || json_decode($str) !== nullผมคิดว่าวิธีการนี้ค่อนข้างจะกลับมา
แอนทอน Pinsard

11

คุณต้องตรวจสอบการป้อนข้อมูลของคุณเพื่อให้แน่ใจว่าสตริงที่คุณส่งไม่ว่างเปล่าและอันที่จริงแล้วคือสตริง สตริงว่างไม่ใช่ JSON ที่ถูกต้อง

function is_json($string) {
  return !empty($string) && is_string($string) && is_array(json_decode($string, true)) && json_last_error() == 0;
}

ผมคิดว่าใน PHP มันเป็นสิ่งสำคัญมากขึ้นในการตรวจสอบว่าวัตถุ JSON แม้มีข้อมูลเพราะการใช้ข้อมูลที่คุณจะต้องโทรหรือjson_encode() json_decode()ฉันขอแนะนำให้ปฏิเสธวัตถุ JSON ที่ว่างเปล่าเพื่อให้คุณไม่จำเป็นต้องใช้การเข้ารหัสและถอดรหัสข้อมูลที่ไม่จำเป็น

function has_json_data($string) {
  $array = json_decode($string, true);
  return !empty($string) && is_string($string) && is_array($array) && !empty($array) && json_last_error() == 0;
}

+1 สำหรับการคิดถึงปัญหาในบริบทของโลกแห่งความเป็นจริง
cartbeforehorse

แต่'0'ไม่ถูกต้อง json ... ทำไมฉันถึงต้องระวัง? @Kzqai
upful

11

สิ่งนี้จะทำ:

function isJson($string) {
    $decoded = json_decode($string); // decode our JSON string
    if ( !is_object($decoded) && !is_array($decoded) ) {
        /*
        If our string doesn't produce an object or array
        it's invalid, so we should return false
        */
        return false;
    }
    /*
    If the following line resolves to true, then there was
    no error and our JSON is valid, so we return true.
    Otherwise it isn't, so we return false.
    */
    return (json_last_error() == JSON_ERROR_NONE);
}

if ( isJson($someJsonString) ) {
    echo "valid JSON";
} else {
    echo "not valid JSON";
}

ดังที่แสดงในคำตอบอื่น ๆjson_last_error()ส่งคืนข้อผิดพลาดจาก json_decode สุดท้ายของเรา () อย่างไรก็ตามมีกรณีการใช้งานขอบบางกรณีที่ฟังก์ชันนี้เพียงอย่างเดียวไม่ครอบคลุมเพียงพอ ตัวอย่างเช่นถ้าคุณjson_decode()เป็นจำนวนเต็ม (เช่น123) หรือสตริงของตัวเลขที่ไม่มีช่องว่างหรืออักขระอื่น ๆ (เช่น: ก"123") ซึ่งเป็นjson_last_error()ฟังก์ชั่นจะไม่จับข้อผิดพลาด

เพื่อต่อสู้กับสิ่งนี้ฉันได้เพิ่มขั้นตอนพิเศษที่ทำให้มั่นใจได้ว่าผลลัพธ์ของเราjson_decode()อาจเป็นวัตถุหรืออาร์เรย์ falseถ้ามันไม่ได้แล้วเราจะกลับ

หากต้องการดูสิ่งนี้ในเชิงปฏิบัติให้ตรวจสอบสองตัวอย่างนี้:


"hello"เป็น JSON ที่ถูกต้องและก็ไม่ได้เป็นวัตถุค่าอาร์เรย์json_last_error()เป็นพอ
JoniJnm

1
json_last_error()ส่งกลับรหัสข้อผิดพลาด4เมื่อคุณสตริงjson_decode() "hello"ตัวอย่างที่นี่: 3v4l.org/lSsEo
Lewis Donovan

รหัสของคุณไม่ถูกต้องhelloไม่ได้เป็น JSON ถูกต้อง แต่"hello"เป็น 3v4l.org/OEJrQ
JoniJnm

9

วิธีง่ายๆคือการตรวจสอบผล json ..

$result = @json_decode($json,true);
    if (is_array($result)) {
        echo 'JSON is valid';
    }else{
        echo 'JSON is not valid';
    }

6

ในGuzzleHttp :

/**
 * Wrapper for json_decode that throws when an error occurs.
 *
 * @param string $json    JSON data to parse
 * @param bool $assoc     When true, returned objects will be converted
 *                        into associative arrays.
 * @param int    $depth   User specified recursion depth.
 * @param int    $options Bitmask of JSON decode options.
 *
 * @return mixed
 * @throws \InvalidArgumentException if the JSON cannot be decoded.
 * @link http://www.php.net/manual/en/function.json-decode.php
 */
function json_decode($json, $assoc = false, $depth = 512, $options = 0)
{
    $data = \json_decode($json, $assoc, $depth, $options);
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \InvalidArgumentException(
            'json_decode error: ' . json_last_error_msg());
    }

    return $data;
}

/**
 * Wrapper for JSON encoding that throws when an error occurs.
 *
 * @param mixed $value   The value being encoded
 * @param int    $options JSON encode option bitmask
 * @param int    $depth   Set the maximum depth. Must be greater than zero.
 *
 * @return string
 * @throws \InvalidArgumentException if the JSON cannot be encoded.
 * @link http://www.php.net/manual/en/function.json-encode.php
 */
function json_encode($value, $options = 0, $depth = 512)
{
    $json = \json_encode($value, $options, $depth);
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \InvalidArgumentException(
            'json_encode error: ' . json_last_error_msg());
    }

    return $json;
}

5

ก่อนหน้านี้ฉันแค่ตรวจสอบค่าว่างซึ่งผิดจริง

    $data = "ahad";
    $r_data = json_decode($data);
    if($r_data){//json_decode will return null, which is the behavior we expect
        //success
    }

โค้ดด้านบนทำงานได้ดีกับสตริง อย่างไรก็ตามทันทีที่ฉันให้หมายเลขจะมีการแยกตัวอย่างเช่น

    $data = "1213145";
    $r_data = json_decode($data);

    if($r_data){//json_decode will return 1213145, which is the behavior we don't expect
        //success
    }

เพื่อแก้ไขสิ่งที่ฉันทำนั้นง่ายมาก

    $data = "ahad";
    $r_data = json_decode($data);

    if(($r_data != $data) && $r_data)
        print "Json success";
    else
        print "Json error";

ทางออกที่ดี จัดการปัญหาการพิมพ์ได้เป็นอย่างดี!
Chaoix

5
//Tested thoroughly, Should do the job:
public static function is_json(string $json):bool
{
    json_decode($json);
    if (json_last_error() === JSON_ERROR_NONE) {
        return true;
    }
    return false;
}

4

อีกวิธีที่ง่าย

function is_json($str)
{
    return is_array(json_decode($str,true));
}

1
สิ่งนี้ไม่ถูกต้อง ประเภท PHP ใด ๆ สามารถเข้ารหัสลงใน JSON เช่นวัตถุสตริง ฯลฯ และฟังก์ชัน json_decode คาดว่าจะส่งคืน สิ่งนี้จะเกิดขึ้นได้ก็ต่อเมื่อคุณถอดรหัสอาร์เรย์เสมอและไม่มีประเภทตัวแปรอื่น ๆ
Chaoix

@Chaoix ใช้json_decode($str,true)ทำให้มันแปลงวัตถุเพื่ออาร์เรย์ดังนั้นมันจะผ่านการตรวจสอบ is_array คุณแก้ไขเกี่ยวกับสตริงจำนวนเต็มเป็นต้นว่า
พอลฟิลลิปส์

ฉันเห็นสิ่งที่คุณหมายถึงเกี่ยวกับพารามิเตอร์ที่สองใน json_encode ฉันยังคิดว่าวิธีแก้ปัญหาของ @Ahad Ali นั้นดีกว่าในแง่ของการพิมพ์และทำ json_decode เพียงครั้งเดียวในอัลกอริทึมของคุณ
Chaoix

4

เราจำเป็นต้องตรวจสอบว่าสตริงที่ส่งผ่านไม่ใช่ตัวเลขเพราะในกรณีนี้ json_decode จะไม่มีข้อผิดพลาดเกิดขึ้น

function isJson($str) {
    $result = false;
    if (!preg_match("/^\d+$/", trim($str))) {
        json_decode($str);
        $result = (json_last_error() == JSON_ERROR_NONE);
    }

    return $result;
}

3

ฉันได้ลองวิธีการแก้ปัญหาบางอย่างแล้ว แต่ก็ไม่ได้ผล ฉันลองสิ่งง่าย ๆ นี้:

$isJson = json_decode($myJSON);

if ($isJson instanceof \stdClass || is_array($isJson)) {
   echo("it's JSON confirmed");
} else {
   echo("nope");
}

ฉันคิดว่าเป็น solutiuon ที่ดีตั้งแต่ JSON ถอดรหัสโดยไม่มีพารามิเตอร์ตัวที่สองให้วัตถุ

แก้ไข: หากคุณรู้ว่าจะป้อนอะไรคุณสามารถปรับรหัสนี้ตามความต้องการของคุณ ในกรณีของฉันฉันรู้ว่าฉันมี Json ซึ่งเริ่มต้นด้วย "{" ดังนั้นฉันไม่จำเป็นต้องตรวจสอบว่าเป็นอาร์เรย์หรือไม่


JSON ของคุณอาจเป็นเพียงแค่อาร์เรย์ซึ่งในกรณีนี้มันจะเป็นอาร์เรย์แทนที่จะเป็น stdClass $ foo = "[1, 1, 2, 3]"; var_dump (json_decode ($ foo)); => array (4) {[0] => int (1) [1] => int (1) [2] => int (2) [3] => int (3)}
Misha Nasledov

3

การใช้ PHPBench กับคลาสต่อไปนี้ผลลัพธ์ที่ได้ด้านล่าง:

<?php

declare(strict_types=1);

/**
 * Benchmark doctrine persistent collection count method vs sizeof toArray
 * Revs is the number of times you want the benchmark to run
 * @Revs(1000)
 * @Iterations(100)
 */
class BenchmarkJson
{
    public function benchCatchValid(): bool
    {
        $validJson = '{"validJson":true}';
        try {
            json_decode($validJson, true, 512, JSON_THROW_ON_ERROR);
            return true;
        } catch(\JsonException $exception) {}
        return false;
    }

    public function benchCatchInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        try {
            json_decode($invalidJson, true, 512, JSON_THROW_ON_ERROR);
            return true;
        } catch(\JsonException $exception) {}
        return false;
    }

    public function benchLastErrorValid(): bool
    {
        $validJson = '{"validJson":true}';
        json_decode($validJson, true);
        return (json_last_error() === JSON_ERROR_NONE);
    }

    public function benchLastErrorInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        json_decode($invalidJson, true);
        return (json_last_error() === JSON_ERROR_NONE);
    }

    public function benchNullValid(): bool
    {
        $validJson = '{"validJson":true}';
        return (json_decode($validJson, true) !== null);
    }

    public function benchNullInvalid(): bool
    {
        $invalidJson = '{"invalidJson"';
        return (json_decode($invalidJson, true) !== null);
    }
}
6 subjects, 600 iterations, 6,000 revs, 0 rejects, 0 failures, 0 warnings
(best [mean mode] worst) = 0.714 [1.203 1.175] 1.073 s)
T: 721.504μs μSD/r 0.089μs μRSD/r: 7.270%
suite: 1343ab9a3590de6065bc0bc6eeb344c9f6eba642, date: 2020-01-21, stime: 12:50:14
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| benchmark     | subject               | set | revs | its | mem_peak   | best    | mean    | mode    | worst   | stdev   | rstdev | diff  |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+
| BenchmarkJson | benchCatchValid       | 0   | 1000 | 100 | 2,980,168b | 0.954μs | 1.032μs | 1.016μs | 1.428μs | 0.062μs | 6.04%  | 1.33x |
| BenchmarkJson | benchCatchInvalid     | 0   | 1000 | 100 | 2,980,184b | 2.033μs | 2.228μs | 2.166μs | 3.001μs | 0.168μs | 7.55%  | 2.88x |
| BenchmarkJson | benchLastErrorValid   | 0   | 1000 | 100 | 2,980,184b | 1.076μs | 1.195μs | 1.169μs | 1.616μs | 0.083μs | 6.97%  | 1.54x |
| BenchmarkJson | benchLastErrorInvalid | 0   | 1000 | 100 | 2,980,184b | 0.785μs | 0.861μs | 0.863μs | 1.132μs | 0.056μs | 6.54%  | 1.11x |
| BenchmarkJson | benchNullValid        | 0   | 1000 | 100 | 2,980,168b | 0.985μs | 1.124μs | 1.077μs | 1.731μs | 0.114μs | 10.15% | 1.45x |
| BenchmarkJson | benchNullInvalid      | 0   | 1000 | 100 | 2,980,184b | 0.714μs | 0.775μs | 0.759μs | 1.073μs | 0.049μs | 6.36%  | 1.00x |
+---------------+-----------------------+-----+------+-----+------------+---------+---------+---------+---------+---------+--------+-------+

สรุป: วิธีที่เร็วที่สุดเพื่อตรวจสอบว่า JSON json_decode($json, true) !== null)ที่ถูกต้องคือการกลับมา


ดีมาก :) ฉันชื่นชมคุณ
มาห์ดี

3

ฉันพบคำถามนี้หลังจากเจอสิ่งที่คล้ายกันในงานของฉันเมื่อวาน วิธีการแก้ปัญหาของฉันในท้ายที่สุดคือการผสมผสานของบางส่วนของวิธีการข้างต้น:

function is_JSON($string) {

  $String_Is_JSON = (is_null(json_decode($string, TRUE))) ? FALSE : TRUE;

  return $String_Is_JSON;
}

2

ฉันไม่รู้เกี่ยวกับประสิทธิภาพหรือความงดงามของโซลูชัน แต่เป็นสิ่งที่ฉันใช้:

if (preg_match('/^[\[\{]\"/', $string)) {
    $aJson = json_decode($string, true);
    if (!is_null($aJson)) {
       ... do stuff here ...
    }
}

เนื่องจากสตริงเข้ารหัส JSON ทั้งหมดของฉันเริ่มต้นด้วย {"มันเพียงพอที่จะทดสอบสิ่งนี้ด้วย RegEx ฉันไม่ได้พูดภาษา RegEx ได้อย่างคล่องแคล่วดังนั้นอาจมีวิธีที่ดีกว่าในการทำเช่นนี้ด้วย: strpos ()อาจเร็วกว่า

เพียงแค่พยายามที่จะให้ในความคุ้มค่าของฉัน

PS เพิ่งอัปเดตสตริง RegEx /^[\[\{]\"/เป็นยังหาสตริงอาร์เรย์ JSON ดังนั้นจึงมองหา ["หรือ {" ที่จุดเริ่มต้นของสตริง


2

ควรเป็นดังนี้:

 function isJson($string)
 {
    // 1. Speed up the checking & prevent exception throw when non string is passed
    if (is_numeric($string) ||
        !is_string($string) ||
        !$string) {
        return false;
    }

    $cleaned_str = trim($string);
    if (!$cleaned_str || !in_array($cleaned_str[0], ['{', '['])) {
        return false;
    }

    // 2. Actual checking
    $str = json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE) && $str && $str != $string;
}

UnitTest

public function testIsJson()
{
    $non_json_values = [
        "12",
        0,
        1,
        12,
        -1,
        '',
        null,
        0.1,
        '.',
        "''",
        true,
        false,
        [],
        '""',
        '[]',
        '   {',
        '   [',
    ];

   $json_values = [
        '{}',
        '{"foo": "bar"}',
        '[{}]',
        '  {}',
        ' {}  '
    ];

   foreach ($non_json_values as $non_json_value) {
        $is_json = isJson($non_json_value);
        $this->assertFalse($is_json);
    }

    foreach ($json_values as $json_value) {
        $is_json = isJson($json_value);
        $this->assertTrue($is_json);
    }
}

ฉันชอบที่คุณกำลังตรวจสอบว่ามันเป็นสตริง ทำงานร่วมกันได้ดีกับโซลูชันแรกเพื่อหลีกเลี่ยงErrorExceptionหากสตริงเป็นอาร์เรย์หรือวัตถุ
sykez

1

การขยายคำตอบนี้มีวิธีต่อไปนี้อย่างไร:

<?php

    $json = '[{"user_id":13,"username":"stack"},{"user_id":14,"username":"over"}]';
    //$json = '12';

    function isJson($string) {
        json_decode($string);
        if(json_last_error() == JSON_ERROR_NONE) {
            if(substr($string,0,1) == '[' && substr($string,-1) == ']') { return TRUE; }
            else if(substr($string,0,1) == '{' && substr($string,-1) == '}') { return TRUE; }
            else { return FALSE; }
        }
    }

    echo isJson($json);
?>

1
ไม่ควรทำการตรวจสอบสตริงย่อยก่อนดำเนินการถอดรหัสเพื่อประหยัดเวลาหากพบข้อผิดพลาดในการตรวจสอบนั้น? ฉันจะจินตนาการว่าการตรวจสอบสตริงย่อย 4 รายการจะเร็วกว่า json_decode แต่หากมีใครสามารถสำรองข้อมูลฉันด้วยสมมติฐานนี้ฉันจะขอบคุณความคิดใด ๆ
ทำเครื่องหมาย

นั่นเป็นข้อโต้แย้งค่าโดยสาร ฉันไม่ทราบเวลาในการดำเนินการ แต่ถ้ามันเร็วกว่านั้น
เจ็ด

1

สวัสดีนี่เป็นตัวอย่างเล็กน้อยจากห้องสมุดของฉันในเงื่อนไขแรกนี้ฉันแค่ตรวจสอบว่าข้อมูลเป็น json แล้วส่งคืนถ้าถอดรหัสถูกต้องโปรดทราบการใช้งาน substr เพื่อประสิทธิภาพ (ฉันยังไม่เห็นไฟล์ json ใด ๆ ที่ไม่ได้เริ่ม โดย {หรือ [

$input=trim($input);
if ((substr($input, 0, 1) == '{' && substr($input, -1) == '}') or (substr($input, 0, 1) == '[' && substr($input, -1) == ']')) {
    $output = json_decode($input, 1);
    if (in_array(gettype($output),['object','array'])) {
        #then it's definitely JSON
    }
}

มี 34 คำตอบที่โพสต์ในคำถามนี้ซึ่งหลายคนก็สมัครรับความเชื่อ (ผิดพลาด) ที่ JSON ต้องแสดงอาร์เรย์หรือวัตถุ คำตอบนี้ทำอะไรที่แตกต่างจากคำตอบอีก 3 โหลหรือไม่?
miken32

1

ข้อเสนอแนะอื่นจากฉัน :)

function isJson(string $string) {
  return ($result = json_decode($string, true)) ? $result : $string;
}

0

ฟังก์ชั่นที่กำหนดเอง

function custom_json_decode(&$contents=NULL, $normalize_contents=true, $force_array=true){

    //---------------decode contents---------------------

    $decoded_contents=NULL;

    if(is_string($contents)){

        $decoded_contents=json_decode($contents,$force_array);

    }

    //---------------normalize contents---------------------

    if($normalize_contents===true){

        if(is_string($decoded_contents)){

            if($decoded_contents==='NULL'||$decoded_contents==='null'){

                $contents=NULL;
            }
            elseif($decoded_contents==='FALSE'||$decoded_contents==='false'){

                $contents=false;
            }
        }
        elseif(!is_null($decoded_contents)){

            $contents=$decoded_contents;
        }
    }
    else{

        //---------------validation contents---------------------

        $contents=$decoded_contents;
    }

    return $contents;
}

กรณี

$none_json_str='hello';

//------------decoding a none json str---------------

$contents=custom_json_decode($none_json_str); // returns 'hello'

//------------checking a none json str---------------

custom_json_decode($none_json_str,false);

$valid_json=false;

if(!is_null($none_json_str)){

    $valid_json=true;

}

ทรัพยากร

https://gist.github.com/rafasashi/93d06bae83cc1a1f440b


0

ฟังก์ชั่นที่สร้างขึ้นใหม่สำหรับความเข้ากันได้ของ PHP 5.2 หากคุณต้องการข้อมูลที่ถอดรหัสได้สำเร็จ:

function try_json_decode( $json, & $success = null ){
  // non-strings may cause warnings
  if( !is_string( $json )){
    $success = false;
    return $json;
  }

  $data = json_decode( $json );

  // output arg
  $success =

    // non-null data: success!
    $data !==  null  ||

    // null data from 'null' json: success!
    $json === 'null' ||

    // null data from '  null  ' json padded with whitespaces: success!
    preg_match('/^\s*null\s*$/', $json );

  // return decoded or original data
  return $success ? $data : $json;
}

การใช้งาน:

$json_or_not = ...;

$data = try_json_decode( $json_or_not, $success );

if( $success )
     process_data( $data );
else what_the_hell_is_it( $data );

การทดสอบบางอย่าง:

var_dump( try_json_decode( array(), $success ), $success );
// ret = array(0){}, $success == bool(false)

var_dump( try_json_decode( 123, $success ), $success );
// ret = int(123), $success == bool(false)

var_dump( try_json_decode('      ', $success ), $success );
// ret = string(6) "      ", $success == bool(false)

var_dump( try_json_decode( null, $success ), $success );
// ret = NULL, $success == bool(false)

var_dump( try_json_decode('null', $success ), $success );
// ret = NULL, $success == bool(true)

var_dump( try_json_decode('  null  ', $success ), $success );
// ret = NULL, $success == bool(true)

var_dump( try_json_decode('  true  ', $success ), $success );
// ret = bool(true), $success == bool(true)

var_dump( try_json_decode('  "hello"  ', $success ), $success );
// ret = string(5) "hello", $success == bool(true)

var_dump( try_json_decode('  {"a":123}  ', $success ), $success );
// ret = object(stdClass)#2 (1) { ["a"]=> int(123) }, $success == bool(true)

0
function is_json($input) {

    $input = trim($input);

    if (substr($input,0,1)!='{' OR substr($input,-1,1)!='}')
        return false;

    return is_array(@json_decode($input, true));
}

2
@ ใช้สำหรับการดีบัก (ซ่อนข้อผิดพลาด) แต่ไม่แนะนำอย่างแน่นอน
aswzen

0

การปรับเปลี่ยนอย่างง่ายเพื่อคำตอบของเฮนริกในการสัมผัสความเป็นไปได้ที่จำเป็นที่สุด

(รวมถึง "{} และ []")

function isValidJson($string) {
    json_decode($string);
    if(json_last_error() == JSON_ERROR_NONE) {

        if( $string[0] == "{" || $string[0] == "[" ) { 
            $first = $string [0];

            if( substr($string, -1) == "}" || substr($string, -1) == "]" ) {
                $last = substr($string, -1);

                if($first == "{" && $last == "}"){
                    return true;
                }

                if($first == "[" && $last == "]"){
                    return true;
                }

                return false;

            }
            return false;
        }

        return false;
    }

    return false;

}

0

วิธีที่เร็วที่สุดที่จะอาจจะถอดรหัสวัตถุ JSON ไปได้ที่จะเป็นวัตถุ PHP / อาร์เรย์:

/**
 * If $value is a JSON encoded object or array it will be decoded 
 * and returned.
 * If $value is not JSON format, then it will be returned unmodified.
 */
function get_data( $value ) {
    if ( ! is_string( $value ) ) { return $value; }
    if ( strlen( $value ) < 2 ) { return $value; }
    if ( '{' != $value[0] && '[' != $value[0] ) { return $value; }

    $json_data = json_decode( $value );
    if ( ! $json_data ) { return $value; }
    return $json_data;
}

0

นี่คือฟังก์ชั่นที่เรียบง่ายและมีประสิทธิภาพที่ฉันสร้างขึ้น (ซึ่งใช้การตรวจสอบสตริงพื้นฐานก่อนที่จะใช้json_decodeกับสตริงที่มีขนาดใหญ่กว่า):

function isJson($string) {
    $response = false;

    if (
        is_string($string) &&
        ($string = trim($string)) &&
        ($stringLength = strlen($string)) &&
        (
            (
                stripos($string, '{') === 0 &&
                (stripos($string, '}', -1) + 1) === $stringLength
            ) ||
            (
                stripos($string, '[{') === 0 &&
                (stripos($string, '}]', -1) + 2) === $stringLength
            )
        ) &&
        ($decodedString = json_decode($string, true)) &&
        is_array($decodedString)
    ) {
        $response = true;
    }

    return $response;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.