为什么WCF/JSON不为null返回值返回`null`?

问题描述:

根据JSON spec,表示空值的正确方法是文字null为什么WCF/JSON不为null返回值返回`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 

$ 
+0

因为空值可以用许多不同的方式表示。看到这篇文章的更多信息:http://*.com/questions/21120999/representing-null-in-json –

+0

@TomRedfern:该帖子的接受答案还声称,null应该表示null应该根据JSON规范。我的问题是*为什么* WCF偏离规范。 – Heinzi

+0

根据[最近的答案](http://*.com/a/39933043/11683),我想知道你的服务是否实际上用'Content-Type:application/json'响应? – GSerg

link以JSON规范包括这些有趣的台词:

JSON是建立在两个结构:

  1. 名称/值对的集合。在各种语言中,这被实现为对象,记录,结构,字典,散列表,键列表或关联数组。

  2. 有序的值列表。在大多数语言中,这是作为数组,矢量,列表或序列实现的。

所以,在我的理解,你的返回类型不符合规范。

  • 无论是public string GetNull() { return null; }

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

要fullfill你将不得不改变他们要匹配1号或2的规格。

  1. 使用结构。 public struct structWithNull{public object resp;}默认值是零,那么返回public structWithNull GetNull() {return new structWithNull() ; }null value returned by struct

  2. 大小为一的阵列使用。 public object[] GetNullArray() {return new object[1] ; }。默认值再次为空;返回: null value returned by one element array

这在我看来,JSON是基于封装数据,如XML,这里总是需要一个父节点。所以我猜想没有其他解决方案来使用struct/class(#1)或数组(#2)。

更新:

我发现了一个线索这里:rfc7159

注意,JSON的某些以前的规格限制的JSON文本是一个对象或数组。只生成对象或数组的JSON文本被调用的实现将是可互操作的,因为所有实现都将接受这些JSON文本为符合条件的JSON文本。

如果我理解正确这,你是正确的,空今天应该返回,因为它是一种原始的,但不会因为主要的重点可能的唯一对象和基于阵列版本的旧规定的行为。

最后我相信只有微软能完全回答这个问题。

+0

这是一个有趣的观点,但我相信你从JSON主页的引用不*暗示有效的JSON文本必须有一个对象或数组作为基本元素。如果我们查看从页面链接的ECMA-404 PDF,我们看到*任何* JSON值都是有效的JSON文本。引用(强调我的):* JSON文本是由Unicode代码点形成的符号序列,符合JSON **值** 语法。 [...] JSON值可以是一个对象,数组,数字,字符串,'true','false'或**'null **。*因此,'null',''''和'“ abc“'是有效的JSON文本,但”(空)不会。 – Heinzi

+0

我发布了一个更新到我的答案。 –

在我看来WCF或其他方式都是数据传输契约,而所有的数据库都是以字符串的形式存在的。区别只是如何缩小字符串表单。
此方法只是返回一个字符串,不管客户端如何获取数据格式如何,所以它不需要是json格式。
如果只是返回字符串"null"代表null如果我想返回字符串"null"而不是null。它会感到困惑。当然你可以使用ESC字符来解决它。也许他们认为没有更好的。
如果客户端使用json格式数据,你只需返回一个字符串"null",然后客户端反序列化它得到一个null,一切都很好。无论如何,返回是无关紧要的,但如何签约数据格式。

+0

是的,唯一重要的是发送者和接收者知道消息的含义。 –

如果你想实际空值在JSON格式的WCF响应中返回,你应该定义一个datacontract并没有初始化它

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

现在,在您操作约定返还像这样

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

然后你会在你的JSON响应中为null值。

希望它有帮助