Ответ 1
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
Мне нужен действительно быстрый метод проверки, является ли строка JSON или нет. Я чувствую, что это не лучший способ:
function isJson($string) {
return ((is_string($string) &&
(is_object(json_decode($string)) ||
is_array(json_decode($string))))) ? true : false;
}
Любые энтузиасты по производительности хотят улучшить этот метод?
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
Ответ на вопрос
Функция 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);
Недопустимый ВЫХОД
Syntax error, malformed JSON.
Дополнительная заметка для (PHP >= 5.2 & PHP < 5.3.0)
Так как json_last_error
не поддерживается в PHP 5.2, вы можете проверить, возвращается ли кодировка или декодирование boolean FALSE
. Вот пример
// decode the JSON data
$result = json_decode($json);
if ($result === FALSE) {
// JSON is invalid
}
Надеюсь, это полезно. Счастливое кодирование!
Все, что вам действительно нужно сделать, это...
if (is_object(json_decode($MyJSONArray)))
{
... do something ...
}
Этот запрос не требует отдельной функции. Просто заверните is_object вокруг json_decode и перейдите. Кажется, у этого решения есть люди, которые слишком много думают о нем.
Используя 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));
Недостаточно энтузиаста производительности, чтобы беспокоиться о контрольных показателях здесь.
Это вернет true, если ваша строка представляет массив 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)
Это самый короткий способ, с которым я могу придумать.
Самый простой и быстрый способ, которым я пользуюсь, заключается в следующем;
$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 в нескольких местах, вы всегда можете использовать следующую функцию.
function is_valid_json( $raw_json ){
return ( json_decode( $raw_json , true ) == NULL ) ? false : true ; // Yes! thats it.
}
В приведенной выше функции вы получите true в ответ, если это правильный JSON.
function is_json($str){
return json_decode($str) != null;
}
http://tr.php.net/manual/en/function.json-decode.php возвращаемое значение равно null, когда обнаружена некорректная кодировка.
Вы должны подтвердить свой ввод, чтобы убедиться, что строка, которую вы передаете, не является пустой и является, фактически, строкой. Пустая строка недействительна 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;
}
Это сделает это:
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 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
.
Чтобы увидеть это в действии, проверьте эти два примера:
Простым методом является проверка результата json.
$result = @json_decode($json,true);
if (is_array($result)) {
echo 'JSON is valid';
}else{
echo 'JSON is not valid';
}
Раньше я просто проверял нулевое значение, что было неправильно.
$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";
в 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;
}
Еще один простой способ
function is_json($str)
{
return is_array(json_decode($str,true));
}
Нам нужно проверить, не является ли принятая строка не числовой, потому что в этом случае 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;
}
Я пробовал некоторые из этих решений, но ничего не работало для меня. Я пробую эту простую вещь:
$isJson = json_decode($myJSON);
if ($isJson instanceof \stdClass || is_array($isJson)) {
echo("it JSON confirmed");
} else {
echo("nope");
}
Я думаю, что это прекрасный solutiuon, поскольку декодирование JSON без второго параметра дает объект.
EDIT: Если вы знаете, какой будет вход, вы можете адаптировать этот код к вашим потребностям. В моем случае я знаю, что у меня есть Json, который начинается с "{", поэтому мне не нужно проверять, является ли это массивом.
Я не знаю о производительности или элегантности моего решения, но это то, что я использую:
if (preg_match('/^[\[\{]\"/', $string)) {
$aJson = json_decode($string, true);
if (!is_null($aJson)) {
... do stuff here ...
}
}
Поскольку все мои закодированные строки JSON начинаются с { ", достаточно проверить это с помощью RegEx.Я совсем не уверен в RegEx, поэтому может быть лучший способ сделать это. Также: strpos() может быть быстрее.
Просто пытаясь дать мне свою ценность.
P.S. Просто обновите строку RegEx до /^[\[\{]\"/
, чтобы найти строки массива JSON. Поэтому теперь он ищет либо [ ", либо {" в начале строки.
Развернуть этот ответ Как насчет следующего:
<?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);
?>
Должно быть что-то вроде этого:
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;
}
Unit тест
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);
}
}
Привет, вот небольшой фрагмент из моей библиотеки, в этом первом условии я просто проверяю, являются ли данные 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 definitely JSON
}
}
Пользовательская функция
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;
}
Ресурсы
Свежеприготовленная функция для совместимости с 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)
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));
}
Простая модификация для henrik отвечает, чтобы коснуться наиболее необходимых возможностей.
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;
}
Самый быстрый способ, возможно, декодировать возможный объект 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;
}
следует рассмотреть некоторые более сложные методы json linting. Я предпочитаю использовать https://github.com/Seldaek/jsonlint, который не возвращает ложные позитивы, упомянутые выше.
Еще одно предложение от меня :)
function isJson(string $string) {
return ($result = json_decode($string, true)) ? $result : $string;
}
if(!empty(json_decode($data)))
{
echo "real json";
}
проверьте его с помощью этой функции:
function is_json($string) {
if (is_string($string) && !is_int($string) && !is_array($string)) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
} else {
return false;
}
}
ive попробовал что-то вроде этого
<?php
/* valid json */
$json1 =
json_encode([
'foo' => 'bar',
'bar',
'foo2 ' => [
'bar' => 'foo',
'try'=> 32,
'foo',
'bar',
[[[[[[]]]]]]
],
'foobar'=>[
'foo'=>'bar',
'bar'=>'foo'
]
]);
$json2 =
json_encode([
'foo' => 'bar',
'bar',
'foo2 ' => [
'bar' => 'foo',
'try'=> 32,
'foo',
'bar',
[[[[[[]]]]]]
],
'foobar'=>[
'foo'=>'bar',
'bar'=>'foo'
]
]) . ';'; // << invalid json
$mt = microtime(1);
for($i=0;$i<1000000;$i++){
check1($json1);
check1($json2);
}
echo "PROCESS TOOK: " . (microtime(1) - $mt) . " seconds\n";
$mt = microtime(1);
for($i=0;$i<1000000;$i++){
check2($json1);
check2($json2);
}
echo "PROCESS TOOK: " . (microtime(1) - $mt) . " seconds\n";
function check1($json){
return preg_match('/(?(DEFINE)(?<number>-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?)(?<boolean>true|false|null)(?<string>"([^"\\\\]*|\\\\["\\\\bfnrt\/]|\\\\u[0-9a-f]{4})*")(?<array>\[(?:(?&json)(?:,(?&json))*)?\s*\])(?<pair>\s*(?&string)\s*:(?&json))(?<object>\{(?:(?&pair)(?:,(?&pair))*)?\s*\})(?<json>\s*(?:(?&number)|(?&boolean)|(?&string)|(?&array)|(?&object))\s*))\A(?&json)\Z/six', $json);
}
function check2($json){
json_decode($json);
return (json_last_error() === JSON_ERROR_NONE);
}
Выход
PROCESS TOOK: 7.5640170574188 seconds
PROCESS TOOK: 4.4907619953156 seconds
существует разница в 3 раза между регулярной функцией выражения и функцией json_decode native, но это происходит после 1 миллиона раз повторения, поэтому она не слишком коротка в любом случае
изменить: после некоторых мыслей я предпочитаю это;
if(checkjson($json)){
echo "this is json :3\n";
var_dump($json);
} else {
die('omg this is not json!!!');
}
function checkjson(&$json){
$json = json_decode($json);
return (json_last_error() === JSON_ERROR_NONE);
}