2016-08-21 2 views
16

Gemäß der JSON spec ist die korrekte Art, einen Nullwert darzustellen, das Literal null.Warum gibt WCF/JSON für einen Null-Rückgabewert nicht null zurück?

Wenn das der Fall ist, warum gibt WCF eine leere Antwort statt null zurück? Ist das ein Fehler oder ist dieses Verhalten irgendwo dokumentiert?

komplettes Repro Beispiel:

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(); 
    } 
} 

Erwartetes Ergebnis:

$ curl http://localhost:8000/GetSomeString && echo 
"SomeString" 
$ curl http://localhost:8000/GetNull && echo 
null 
$ 

Tatsächliches Ergebnis:

$ curl http://localhost:8000/GetSomeString && echo 
"SomeString" 
$ curl http://localhost:8000/GetNull && echo 

$ 
+0

Weil ein Nullwert auf viele verschiedene Arten dargestellt werden kann. Siehe diesen Beitrag für mehr: http://StackOverflow.com/Questions/21120999/representting-null-in-json –

+0

@TomRedfern: Die akzeptierte Antwort dieses Beitrags behauptet auch, dass "null" ist die Art und Weise Null sollte entsprechend dargestellt werden die JSON-Spezifikation Meine Frage ist * warum * WCF von der Spezifikation abweicht. – Heinzi

+0

In Anbetracht der [letzten Antwort] (http://stackoverflow.com/a/39933043/11683), frage ich mich, ob Ihr Dienst tatsächlich mit "Content-Type: application/json" antwortet? – GSerg

Antwort

6

Ihre link zu json Spezifikation dieser interessanten Zeilen umfasst:

JSON ist auf zwei Strukturen aufgebaut:

  1. Eine Sammlung von Name/Wert-Paare. In verschiedenen Sprachen wird dies als Objekt, Datensatz, Struktur, Wörterbuch, Hash-Tabelle, codierte Liste oder assoziatives Array realisiert.

  2. Eine geordnete Liste der Werte. In den meisten Sprachen wird dies als Array, Vektor, Liste oder Sequenz realisiert.

Also, in meinem Verständnis, Ihre Rückgabetypen sind nicht konform mit der Spezifikation.

  • Weder public string GetNull() { return null; }

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

Um die Spezifikationen erfüllen Sie sie ändern müssten entweder # 1 oder # 2 entsprechen.

  1. Eine Struktur wird verwendet. public struct structWithNull{public object resp;} Der Standardwert ist null, so public structWithNull GetNull() {return new structWithNull() ; } Rückkehr: null value returned by struct

  2. Ein Array von einer Größe verwendet wird. public object[] GetNullArray() {return new object[1] ; }. Der Standardwert ist wieder null. es gibt: null value returned by one element array

Es scheint mir, dass JSON basiert Daten von Einkapselung, wie XML, wo ein Elternknoten immer benötigt wird. Also denke ich, dass es keine andere Lösung gibt, um eine Struktur/Klasse (# 1) oder ein Array (# 2) zu verwenden.

Update:

fand ich einen Hinweis hier: rfc7159

Beachten Sie, dass bestimmte vorherigen Spezifikationen von JSON eingeschränkt einen JSON Text ein Objekt oder ein Array zu sein. Implementierungen, die nur Objekte oder Arrays erzeugen, für die ein JSON-Text aufgerufen wird, sind in dem Sinne interoperabel, dass alle Implementierungen diese als konforme JSON-Texte akzeptieren.

Wenn ich das richtig verstehe, sind Sie richtig und null sollte heute zurückgegeben werden, da es ein primitiv ist, aber nicht, weil der Hauptfokus auf dem alten spezifizierten Verhalten der einzigen Objekt und Array-basierten Versionen sein könnte .

Endlich glaube ich, dass nur Microsoft diese Frage vollständig beantworten kann.

+0

Das ist ein interessanter Punkt, aber ich glaube, dass Ihr Zitat von der JSON-Homepage * nicht * impliziert, dass ein gültiger JSON-Text ein Objekt oder Array als Basiselement haben muss. Wenn wir die PDF-Datei von ECMA-404 betrachten, die von der Seite verlinkt ist, sehen wir, dass * jeder * JSON-Wert ein gültiger JSON-Text ist. Um zu zitieren (Hervorhebung von mir): * Ein JSON-Text ist eine Folge von Token, die aus Unicode-Codepunkten gebildet sind, die der JSON ** -Wert ** Grammatik entsprechen. [...] Ein JSON-Wert kann ein Objekt, Array, Zahl, String, 'true',' false' oder ** 'null' ** sein. * Also,' null', '" "' und '" abc "' wären gültige JSON-Texte, aber '' (leer) nicht. – Heinzi

+0

Ich habe ein kleines Update zu meiner Antwort gepostet. –

0

Meiner Meinung nach WCF oder andere Möglichkeiten sind Datenübertragungsvertrag, und alle Daten auf String. Unterschied nur, wie Sie die Zeichenkette zusammenziehen.
Diese Methode gibt nur eine Zeichenkette zurück, egal wie das Format ist, nur der Client kann die Daten erhalten, also muss es kein JSON-Format sein.
Wenn nur String zurückgeben "null" stellen null dar, wenn ich String "null" anstelle von null zurückgeben möchte. Es wird verwirrt sein. Natürlich können Sie ESC-Zeichen verwenden, um es zu lösen. Vielleicht denken sie, nichts ist besser.
Wenn Client JSON Format Daten verwenden, geben Sie einfach eine Zeichenfolge "null", Client deserialize es erhalten eine null, alles ist in Ordnung. Wie auch immer, es spielt keine Rolle, welche Rendite, sondern wie man das Datenformat anpasst.

+0

Ja, es ist nur wichtig, dass Absender und Empfänger wissen, was mit einer Nachricht gemeint ist. –

-1

Wenn Sie tatsächliche Nullwerte werden möchten in Ihrer wcf Antwort im JSON-Format zurückgegeben Sie eine Datacontract definieren sollten und es zurück, ohne es zu initialisieren

[DataContract] 
public class Employee 
{ 
[DataMember] 
public string id { get; set; } 
} 

Jetzt ist es in Ihrem Betrieb Vertrag zurückgeben wie diese

[OperationContract(), WebGet(ResponseFormat = WebMessageFormat.Json)] 
public string GetNull() { return new Employee(); } 

Dann werden Sie Null-Werte in Ihrer JSON-Antwort.

Hoffe es hilft

Verwandte Themen