Почему 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 список или ассоциативный массив.

  • Упорядоченный список значений. В большинстве языков это реализуется как массив, вектор, список или последовательность.

Итак, в моем понимании, ваши типы возврата не соответствуют спецификации.

  • Ни public string GetNull() { return null; }

  • и public string GetSomeString() { return "SomeString"; }

Чтобы заполнить спецификации, вам нужно будет их изменить, чтобы соответствовать # 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.

Надеюсь, что это поможет