Почему WCF/JSON не возвращает null для нулевого возвращаемого значения?
В соответствии со спецификацией JSON правильный способ представления нулевого значения - это буквальный null
.
Если это так, почему WCF возвращает пустой ответ вместо null
? Является ли это ошибкой или это где-то документировано?
Полный пример воспроизведения:
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
[ServiceContract()]
public class Service1
{
[OperationContract(), WebGet(ResponseFormat = WebMessageFormat.Json)]
public string GetSomeString() { return "SomeString"; }
[OperationContract(), WebGet(ResponseFormat = WebMessageFormat.Json)]
public string GetNull() { return null; }
}
public class Host
{
public static void Main()
{
// Very simple WCF server
var host = new WebServiceHost(typeof(Service1), new Uri("http://localhost:8000/"));
host.AddServiceEndpoint(typeof(Service1), new WebHttpBinding() {
HostNameComparisonMode = HostNameComparisonMode.Exact
}, "");
host.Open();
Console.WriteLine("Service is running, press enter to quit...");
Console.ReadLine();
host.Close();
}
}
Ожидаемый результат:
$ curl http://localhost:8000/GetSomeString && echo
"SomeString"
$ curl http://localhost:8000/GetNull && echo
null
$
Фактический результат:
$ curl http://localhost:8000/GetSomeString && echo
"SomeString"
$ curl http://localhost:8000/GetNull && echo
$
Ответы
Ответ 1
Ваша ссылка в json включает в себя следующие интересные строки:
JSON построен на двух структурах:
-
Коллекция пар имя/значение. На разных языках это реализуется как объект, запись, структура, словарь, хеш-таблица, keyed список или ассоциативный массив.
-
Упорядоченный список значений. В большинстве языков это реализуется как массив, вектор, список или последовательность.
Итак, в моем понимании, ваши типы возврата не соответствуют спецификации.
Чтобы заполнить спецификации, вам нужно будет их изменить, чтобы соответствовать # 1 или # 2.
-
Используется структура. public struct structWithNull{public object resp;}
Значение по умолчанию равно null, поэтому public structWithNull GetNull() {return new structWithNull() ; }
возвращает:
![значение null, возвращаемое struct]()
-
Используется массив размера один. public object[] GetNullArray() {return new object[1] ; }
. Значение по умолчанию равно null; он возвращает:
![значение null, возвращаемое одним массивом элементов]()
Мне кажется, что JSON основан на инкапсулировании данных, таких как XML, где всегда нужен родительский node. Поэтому я предполагаю, что нет другого решения для этого, как использовать struct/class (# 1) или массив (# 2).
Update:
Я нашел ключ здесь: rfc7159
Обратите внимание, что некоторые предыдущие спецификации JSON ограничивали текст JSON как объект или массив. Реализации, которые генерируют только объекты или массивы, в которых вызывается текст JSON, будут взаимодействовать в том смысле, что все реализации будут воспринимать их как соответствующие тексты JSON.
Если я правильно это понимаю, вы правы, и null должен быть возвращен сегодня, поскольку он является примитивным, но не потому, что основной фокус может быть в отношении старого заданного поведения только для версий на основе объектов и массивов.
Наконец, я считаю, что только Microsoft может полностью ответить на этот вопрос.
Ответ 2
По-моему, WCF или другие способы - это контракт передачи данных и вся база данных по строке. Разница только в том, как вы сокращаете строчную форму.
Этот метод просто возвращает строку, независимо от того, как формат только клиент может получить данные, поэтому ему не нужно быть json-форматом.
Если просто вернуть строку "null"
представить null
, что, если я хочу вернуть строку "null"
вместо null
. Это будет смущено. Конечно, вы можете использовать ESC символы решить его. Может быть, они думают, что ничего лучше.
Если клиент использует данные формата json, вы просто возвращаете строку "null"
, а затем десериализуете ее, получаем null
, все в порядке. Во всяком случае, не имеет значения, какое возвращение, но как скомпилировать формат данных.
Ответ 3
Если вы хотите, чтобы фактические нулевые значения возвращались в вашем ответе wcf в формате json, вы должны определить datacontract и вернуть его без инициализации
[DataContract]
public class Employee
{
[DataMember]
public string id { get; set; }
}
Теперь в вашем операционном контракте верните его так:
[OperationContract(), WebGet(ResponseFormat = WebMessageFormat.Json)]
public string GetNull() { return new Employee(); }
Затем вы получите нулевые значения в ответе json.
Надеюсь, что это поможет