Представление нулевого значения в JSON
Каков предпочтительный метод для возврата нулевых значений в JSON? Есть ли другое предпочтение примитивам?
Например, если у моего объекта на сервере есть Integer с именем "myCount" без значения, наиболее правильным JSON для этого значения будет:
{}
или же
{
"myCount": null
}
или же
{
"myCount": 0
}
Тот же вопрос для строк - если у меня есть пустая строка "myString" на сервере, лучше всего JSON:
{}
или же
{
"myString": null
}
или же
{
"myString": ""
}
или (господин, помоги мне)
{
"myString": "null"
}
Мне нравится соглашение о представлении коллекций в JSON в виде пустой коллекции http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html
Пустой массив будет представлен:
{
"myArray": []
}
РЕДАКТИРОВАТЬ Резюме
Аргумент "личных предпочтений" кажется реалистичным, но недальновидным в этом, поскольку в качестве сообщества мы будем потреблять все большее количество разрозненных услуг/источников. Соглашения для структуры JSON помогут нормализовать потребление и повторное использование указанных услуг. Что касается установления стандарта, я бы предложил принять большинство соглашений Джексона с несколькими исключениями:
- Объекты предпочтительнее примитивов.
- Пустые коллекции предпочтительнее нуля.
- Объекты без значения представлены как ноль.
- Примитивы возвращают свою ценность.
Если вы возвращаете объект JSON с большей частью нулевыми значениями, у вас может быть кандидат на рефакторинг в несколько сервисов.
{
"value1": null,
"value2": null,
"text1": null,
"text2": "hello",
"intValue": 0, //use primitive only if you are absolutely sure the answer is 0
"myList": [],
"myEmptyList": null, //NOT BEST PRACTICE - return [] instead
"boolean1": null, //use primitive only if you are absolutely sure the answer is true/false
"littleboolean": false
}
Вышеупомянутый JSON был сгенерирован из следующего класса Java.
package jackson;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonApp {
public static class Data {
public Integer value1;
public Integer value2;
public String text1;
public String text2 = "hello";
public int intValue;
public List<Object> myList = new ArrayList<Object>();
public List<Object> myEmptyList;
public Boolean boolean1;
public boolean littleboolean;
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new Data()));
}
}
Maven зависимость:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>
Ответы
Ответ 1
Давайте оценим разбор каждого:
http://jsfiddle.net/brandonscript/Y2dGv/
var json1 = '{}';
var json2 = '{"myCount": null}';
var json3 = '{"myCount": 0}';
var json4 = '{"myString": ""}';
var json5 = '{"myString": "null"}';
var json6 = '{"myArray": []}';
console.log(JSON.parse(json1)); // {}
console.log(JSON.parse(json2)); // {myCount: null}
console.log(JSON.parse(json3)); // {myCount: 0}
console.log(JSON.parse(json4)); // {myString: ""}
console.log(JSON.parse(json5)); // {myString: "null"}
console.log(JSON.parse(json6)); // {myArray: []}
TL; Dr здесь:
Фрагмент в переменной json2 - это способ, которым спецификация JSON указывает, что null
должен быть представлен. Но, как всегда, это зависит от того, что вы делаете - иногда "правильный" способ сделать это не всегда работает в вашей ситуации. Используйте свое суждение и примите обоснованное решение.
JSON1 {}
Это возвращает пустой объект. Там нет данных, и он только скажет вам, что любой ключ, который вы ищете (будь то myCount
или что-то еще), имеет тип undefined
.
JSON2 {"myCount": null}
В этом случае myCount
фактически определен, хотя его значение равно null
. Это не то же самое, что оба "не undefined
и не равно null
", и если вы тестировали одно или другое условие, это могло бы быть успешным, в то время как JSON1 потерпел бы неудачу.
Это точный способ представления null
в спецификации JSON.
JSON3 {"myCount": 0}
В этом случае myCount равен 0. Это не то же самое, что null
, и это не то же самое, что и false
. Если ваш условный оператор оценивает myCount > 0
, то это может быть полезно. Более того, если вы выполняете расчеты на основе значения здесь, 0 может быть полезно. Однако, если вы пытаетесь проверить на null
, это вообще не сработает.
JSON4 {"myString": ""}
В этом случае вы получаете пустую строку. Опять же, как и в JSON2, он определен, но пуст. Вы можете проверить для if (obj.myString == "")
но вы не можете проверить для null
или undefined
.
JSON5 {"myString": "null"}
Это, вероятно, доставит вам неприятности, потому что вы устанавливаете строковое значение в null; в этом случае obj.myString == "null"
однако это не == null
.
JSON6 {"myArray": []}
Это скажет вам, что ваш массив myArray
существует, но он пустой. Это полезно, если вы пытаетесь выполнить подсчет или оценку на myArray
. Например, предположим, что вы хотите оценить количество фотографий, которые опубликовал пользователь - вы можете сделать myArray.length
и он вернет 0
: определено, но фотографии не опубликованы.
Ответ 2
null
не равен нулю. Это не значение, как таковое: это значение вне домена переменной, указывающее отсутствующие или неизвестные данные.
В JSON существует только один способ представления null
. По спецификациям (RFC 4627 и json.org):
2.1. Values
A JSON value MUST be an object, array, number, or string, or one of
the following three literal names:
false null true
![enter image description here]()
Ответ 3
Существует только один способ представления null
; то есть с null
.
console.log(null === null); // true
console.log(null === true); // false
console.log(null === false); // false
console.log(null === 'null'); // false
console.log(null === "null"); // false
console.log(null === ""); // false
console.log(null === []); // false
console.log(null === 0); // false
То есть; если любой из клиентов, которые потребляют ваше представление JSON, использует оператор ===
; это может быть проблемой для них.
нет значения
Если вы хотите сообщить, что у вас есть объект, чей атрибут myCount
не имеет значения:
{ "myCount": null }
атрибут/отсутствующий атрибут
Что, если вы передадите, что у вас есть объект без атрибутов:
{}
Клиентский код попытается получить доступ к myCount
и получить undefined
; это не так.
пустая коллекция
Что, если вы передадите, что у вас есть объект с атрибутом myCount
, который является пустым списком:
{ "myCount": [] }
Ответ 4
Я бы использовал null
чтобы показать, что для данного ключа нет значения. Например, используйте null
чтобы указать, что "количество устройств в вашей семье, подключенных к Интернету" неизвестно.
С другой стороны, используйте {}
если этот конкретный ключ не применим. Например, вам не следует показывать счет, даже если он null
, на вопрос "количество автомобилей с активным интернет-соединением" задается тому, кто не владеет автомобилями.
Я бы не стал использовать любое значение по умолчанию, если это значение не имеет смысла. Хотя вы можете решить использовать null
для представления значения, конечно, никогда не используйте "null"
для этого.
Ответ 5
Я бы выбрал "по умолчанию" для типа данных переменной (null
для строк/объектов, 0
для чисел), но действительно проверьте, какой код будет потреблять объект. Не забывайте, что иногда существует разница между null
/default vs. "not present".
Проверьте шаблон нулевого объекта - иногда лучше передать некоторый специальный объект вместо null
(т.е. []
array вместо null
для массивов или ""
для строк).
Ответ 6
Это личный и ситуативный выбор. Важно помнить, что пустая строка и нуль концептуально отличаются от null
.
В случае count
вы, вероятно, всегда хотите какое-то действительное число (если только count
неизвестно или undefined), но в случае строк, кто знает? Пустая строка может означать что-то в вашем приложении. Или, может быть, нет. Это вам решать.
Ответ 7
Согласно спецификации JSON, внешний контейнер не обязательно должен быть словарем (или "объектом"), как подразумевается в большинстве комментариев выше. Это также может быть список или пустое значение (то есть строка, число, логическое значение или ноль). Если вы хотите представить нулевое значение в JSON, вся строка JSON (исключая кавычки, содержащие строку JSON) будет просто null
. Без скобок, без скобок, без кавычек. Вы можете указать словарь, содержащий ключ с нулевым значением ({"key1":null}
), или список с нулевым значением ([null]
), но сами они не являются нулевыми значениями - это правильные словари и списки. Точно так же пустой словарь ({}
) или пустой список ([]
) вполне подойдут, но и не равны нулю.
В Python:
>>> print json.loads('{"key1":null}')
{u'key1': None}
>>> print json.loads('[null]')
[None]
>>> print json.loads('[]')
[]
>>> print json.loads('{}')
{}
>>> print json.loads('null')
None