Сначала у вас есть строка. JSON не является массивом, объектом или структурой данных. JSON - текстовый формат сериализации - так что причудливая строка, но все же просто строка. Декодируйте его в PHP с помощью json_decode()
.
$data = json_decode($json);
В нем вы можете найти:
Это то, что может быть закодировано в JSON. Или, точнее, это версии PHP, которые могут быть закодированы в JSON.
В них нет ничего особенного. Они не являются объектами JSON или массивами JSON. Вы расшифровали JSON - теперь у вас есть основные повседневные типы PHP .
Объекты будут экземплярами stdClass , встроенным классом, который просто generic thing , что здесь не важно.
Вы получаете доступ к свойствам одного из этих объектов так же, как и для публичных нестатических свойств любого другого объекта, например $object->property
.
$json = '
{
"type": "donut",
"name": "Cake"
}';
$yummy = json_decode($json);
echo $yummy->type; //donut
Доступ к элементам одного из этих массивов осуществляется так же, как и для любого другой массив, например $array[0]
.
$json = '
[
"Glazed",
"Chocolate with Sprinkles",
"Maple"
]';
$toppings = json_decode($json);
echo $toppings[1]; //Chocolate with Sprinkles
Итерации над ним с помощью foreach
.
foreach ($toppings as $topping) {
echo $topping, "\n";
}
Глазурованный Шоколад с спринклерами Maple
Или беспорядок с любой из встроенных функций bazillion [].
Доступ к вложенные элементы
Свойства объектов и элементов массивов могут быть больше объектов и / или массивов - вы можете просто продолжать доступ к своим свойствам и членам как обычно, например
$object->array[0]->etc
.$json = ' { "type": "donut", "name": "Cake", "toppings": [ { "id": "5002", "type": "Glazed" }, { "id": "5006", "type": "Chocolate with Sprinkles" }, { "id": "5004", "type": "Maple" } ] }'; $yummy = json_decode($json); echo $yummy->toppings[2]->id; //5004
Передача
true
в качестве второго аргумента в json_decode ()Когда вы это сделаете, вместо объектов вы получите ассоциативные массивы - массивы со строками для ключей. Снова вы получаете доступ к их элементам, как обычно, например.
$array['key']
.$json = ' { "type": "donut", "name": "Cake", "toppings": [ { "id": "5002", "type": "Glazed" }, { "id": "5006", "type": "Chocolate with Sprinkles" }, { "id": "5004", "type": "Maple" } ] }'; $yummy = json_decode($json, true); echo $yummy['toppings'][2]['type']; //Maple
Не знаю, как структурированы данные
Прочитайте документацию, независимо от того, получение JSON из.
Посмотрите на JSON - где вы видите фигурные скобки
{}
, ожидайте объект, где вы видите квадратные скобки[]
, ожидаете массив.Нажмите декодированные данные с помощью
print_r()
:$json = ' { "type": "donut", "name": "Cake", "toppings": [ { "id": "5002", "type": "Glazed" }, { "id": "5006", "type": "Chocolate with Sprinkles" }, { "id": "5004", "type": "Maple" } ] }'; $yummy = json_decode($json); print_r($yummy);
и проверьте вывод:
stdClass Object ( [type] => donut [name] => Cake [toppings] => Array ( [0] => stdClass Object ( [id] => 5002 [type] => Glazed ) [1] => stdClass Object ( [id] => 5006 [type] => Chocolate with Sprinkles ) [2] => stdClass Object ( [id] => 5004 [type] => Maple ) ) )
Он расскажет вам, где у вас есть объекты, где у вас есть массивы, а также имена и значения их членов.
Если вы можете только дойти до него до того, как потеряетесь, зайдите так далеко и нажмите , что с
print_r()
:print_r($yummy->toppings[0]);
stdClass Object ( [id] => 5002 [type] => Glazed )
Разбить проблему на части, которые легче обернуть вокруг головы.
json_decode()
возвращаетnull
Это происходит потому, что либо:
- JSON полностью состоит именно из этого,
null
.- JSON is недействителен - проверьте результат
json_last_error_msg
или введите его через JSONLi nt .- Он содержит элементы, вложенные в глубину более 512 уровней. Эта максимальная глубина по умолчанию может быть переопределена путем передачи целого числа в качестве третьего аргумента в
json_decode()
.Если вам нужно изменить максимальную глубину, вы, вероятно, решение неправильной проблемы. Узнайте, почему вы получаете такие глубоко вложенные данные (например, у службы, к которой вы обращаетесь, у которой возникает JSON, есть ошибка) и получить это, чтобы этого не произошло.
Имя свойства объекта содержит специальный символ
Иногда у вас будет имя свойства объекта, которое содержит нечто вроде дефиса
-
или знака@
, которое не может использоваться в литеральном идентификаторе. Вместо этого вы можете использовать строковый литерал в фигурных скобках для его адресации.$json = '{"@attributes":{"answer":42}}'; $thing = json_decode($json); echo $thing->{'@attributes'}->answer; //42
Если у вас есть свойство integer as: Как получить доступ к свойствам объекта с именами типа целых чисел? как ссылка.
Кто-то поставил JSON в ваш JSON
Это смешно, но это происходит - JSON закодирован как строка в вашем JSON. Декодирование, доступ к строке как обычно, декодирование , которое , и, в конечном счете, доступ к тому, что вам нужно.
$json = ' { "type": "donut", "name": "Cake", "toppings": "[{ \"type\": \"Glazed\" }, { \"type\": \"Maple\" }]" }'; $yummy = json_decode($json); $toppings = json_decode($yummy->toppings); echo $toppings[0]->type; //Glazed
Данные не помещаются в память
Если ваш JSON слишком большой для
json_decode()
, чтобы обрабатывать сразу, все начинает становиться сложным. См. Также:Как отсортировать его
См.: Ссылка: все основные способы сортировки массивов и данных в PHP .
Вы можете использовать sysout-over-slf4j .
Модуль sysout-over-slf4j позволяет пользователю перенаправлять все вызовы в System.out и System. err к определенному логгеру SLF4J с именем полного класса, в котором был выполнен вызов System.out.println (или аналогичный), на настраиваемых уровнях.
blockquote>Если вы не используете Maven, загрузите банку и добавьте ее в свой путь к классу.
В качестве альтернативы добавьте ее как зависимость от Maven:
<dependency> <groupId>uk.org.lidalia</groupId> <artifactId>sysout-over-slf4j</artifactId> <version>1.0.2</version> </dependency>
Затем при запуске приложения, вызов :
SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
Я решил проблему, используя LoggingOutputStream для log4j и немного изменил его для slf4j.
import java.io.IOException;
import java.io.PrintStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SysStreamsLogger {
private static Logger sysOutLogger = LoggerFactory.getLogger("SYSOUT");
private static Logger sysErrLogger = LoggerFactory.getLogger("SYSERR");
public static final PrintStream sysout = System.out;
public static final PrintStream syserr = System.err;
protected static final String LINE_SEPERATOR = System.getProperty("line.separator");
public static void bindSystemStreams() {
// Enable autoflush
System.setOut(new PrintStream(new LoggingOutputStream(sysOutLogger, false), true));
System.setErr(new PrintStream(new LoggingOutputStream(sysErrLogger, true), true));
}
public static void unbindSystemStreams() {
System.setOut(sysout);
System.setErr(syserr);
}
private static class LoggingOutputStream extends java.io.OutputStream {
protected Logger log;
protected boolean isError;
/**
* Used to maintain the contract of {@link #close()}.
*/
protected boolean hasBeenClosed = false;
/**
* The internal buffer where data is stored.
*/
protected byte[] buf;
/**
* The number of valid bytes in the buffer. This value is always in the
* range <tt>0</tt> through <tt>buf.length</tt>; elements
* <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid byte
* data.
*/
protected int count;
/**
* Remembers the size of the buffer for speed.
*/
private int bufLength;
/**
* The default number of bytes in the buffer. =2048
*/
public static final int DEFAULT_BUFFER_LENGTH = 2048;
private LoggingOutputStream() {
// illegal
}
/**
* Creates the LoggingOutputStream to flush to the given Category.
*
* @param log
* the Logger to write to
*
* @param isError
* the if true write to error, else info
*
* @exception IllegalArgumentException
* if cat == null or priority == null
*/
public LoggingOutputStream(Logger log, boolean isError) throws IllegalArgumentException {
if (log == null) {
throw new IllegalArgumentException("log == null");
}
this.isError = isError;
this.log = log;
bufLength = DEFAULT_BUFFER_LENGTH;
buf = new byte[DEFAULT_BUFFER_LENGTH];
count = 0;
}
/**
* Closes this output stream and releases any system resources
* associated with this stream. The general contract of
* <code>close</code> is that it closes the output stream. A closed
* stream cannot perform output operations and cannot be reopened.
*/
@Override
public void close() {
flush();
hasBeenClosed = true;
}
/**
* Writes the specified byte to this output stream. The general contract
* for <code>write</code> is that one byte is written to the output
* stream. The byte to be written is the eight low-order bits of the
* argument <code>b</code>. The 24 high-order bits of <code>b</code> are
* ignored.
*
* @param b
* the <code>byte</code> to write
*/
@Override
public void write(final int b) throws IOException {
if (hasBeenClosed) {
throw new IOException("The stream has been closed.");
}
// don't log nulls
if (b == 0) {
return;
}
// would this be writing past the buffer?
if (count == bufLength) {
// grow the buffer
final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH;
final byte[] newBuf = new byte[newBufLength];
System.arraycopy(buf, 0, newBuf, 0, bufLength);
buf = newBuf;
bufLength = newBufLength;
}
buf[count] = (byte) b;
count++;
}
/**
* Flushes this output stream and forces any buffered output bytes to be
* written out. The general contract of <code>flush</code> is that
* calling it is an indication that, if any bytes previously written
* have been buffered by the implementation of the output stream, such
* bytes should immediately be written to their intended destination.
*/
@Override
public void flush() {
if (count == 0) {
return;
}
// don't print out blank lines; flushing from PrintStream puts out
// these
if (count == LINE_SEPERATOR.length()) {
if (((char) buf[0]) == LINE_SEPERATOR.charAt(0) && ((count == 1) || // <-
// Unix
// &
// Mac,
// ->
// Windows
((count == 2) && ((char) buf[1]) == LINE_SEPERATOR.charAt(1)))) {
reset();
return;
}
}
final byte[] theBytes = new byte[count];
System.arraycopy(buf, 0, theBytes, 0, count);
if (isError) {
log.error(new String(theBytes));
} else {
log.info(new String(theBytes));
}
reset();
}
private void reset() {
// not resetting the buffer -- assuming that if it grew that it
// will likely grow similarly again
count = 0;
}
}
}
Теперь можно перенаправить Sytem.out / err на вызывая SysStreamsLogger.bindSystemStreams()
в начале вашего приложения.
Вывод регистрации выглядит следующим образом (из запуска OpenEJB)
2012-06-27 13:44:12,792 INFO [main:] SYSOUT:181 - Apache OpenEJB 3.1.4 build: 20101112-03:32
2012-06-27 13:44:12,793 INFO [main:] SYSOUT:181 - http://openejb.apache.org/