Представление нулевого значения в 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