2013-05-21 21 views
3

我試圖從WCF REST服務返回一個字典作爲JSON對象。我想格式爲 {「key」:「value」} 所以我創建了我自己的類,如herehere所述。來自WCF的JSON響應轉義名稱值

該服務方法的工作原理,排序。問題是鍵名被轉義。例如,如果我的字典包含「Hello world」:100,我會得到 {「Hello_x0020_world」:100}。它也逃脫像%等其他字符等。

有沒有什麼辦法可以告訴序列化不要逃避名稱的方式?這幾乎就像它使用的XML規則不(一定)適用於JSON。

我的序列化類:

[Serializable] 
public class JsonDictionary : ISerializable 
{ 
    private Dictionary<string, object> _Dictionary; 
    public JsonDictionary() 
    { 
     _Dictionary = new Dictionary<string, object>(); 
    } 
    public JsonDictionary(SerializationInfo info, StreamingContext context) 
    { 
     _Dictionary = new Dictionary<string, object>(); 
     SerializationInfoEnumerator enumerator = info.GetEnumerator(); 
     while (enumerator.MoveNext()) 
     { 
      _Dictionary.Add(enumerator.Name, enumerator.Value); 
     } 
    } 
    public object this[string key] 
    { 
     get { return _Dictionary[key]; } 
     set { _Dictionary[key] = value; } 
    } 
    public void Add(string key, object value) 
    { 
     _Dictionary.Add(key, value); 
    } 
    public bool ContainsKey(string key) 
    { 
     return _Dictionary.ContainsKey(key); 
    } 
    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     foreach (string key in _Dictionary.Keys) 
      info.AddValue(key, _Dictionary[key], _Dictionary[key] == null ? typeof(object) : _Dictionary[key].GetType()); 
    } 
} 

我的服務功能定義:

[WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)] 
    public JsonDictionary GetCollection() 
    { 
     JsonDictionary dict = new JsonDictionary(); 

     dict.Add("Hello world", 100); 
     return dict; 
    } 
+0

我一直很喜歡JSON在瀏覽器上的工作方式。如果你無法忍受開銷,那麼你需要一個流中的JSON壓縮器和一個客戶端上的解壓縮器。有很多在那裏 – danny117

回答

1

默認情況下,WCF使用的DataContractJsonSerializer使用XML到JSON的映射這會導致一些問題,比如一個你在ISerializable類型中看到。但是,您可以使用自定義格式化程序來更改響應的序列化方式。在下面的例子中,我使用JSON.NET,它正確地處理ISerializable對象。

public class StackOverflow_16674152 
{ 
    [Serializable] 
    public class JsonDictionary : ISerializable 
    { 
     private Dictionary<string, object> _Dictionary; 
     public JsonDictionary() 
     { 
      _Dictionary = new Dictionary<string, object>(); 
     } 
     public JsonDictionary(SerializationInfo info, StreamingContext context) 
     { 
      _Dictionary = new Dictionary<string, object>(); 
      SerializationInfoEnumerator enumerator = info.GetEnumerator(); 
      while (enumerator.MoveNext()) 
      { 
       _Dictionary.Add(enumerator.Name, enumerator.Value); 
      } 
     } 
     public object this[string key] 
     { 
      get { return _Dictionary[key]; } 
      set { _Dictionary[key] = value; } 
     } 
     public void Add(string key, object value) 
     { 
      _Dictionary.Add(key, value); 
     } 
     public bool ContainsKey(string key) 
     { 
      return _Dictionary.ContainsKey(key); 
     } 
     public void GetObjectData(SerializationInfo info, StreamingContext context) 
     { 
      foreach (string key in _Dictionary.Keys) 
       info.AddValue(key, _Dictionary[key], _Dictionary[key] == null ? typeof(object) : _Dictionary[key].GetType()); 
     } 
    } 
    [ServiceContract] 
    public class Service 
    { 
     [WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)] 
     [MyISerializableResponseJsonBehavior] 
     public JsonDictionary GetCollection() 
     { 
      JsonDictionary dict = new JsonDictionary(); 

      dict.Add("Hello world", 100); 
      return dict; 
     } 
    } 
    public class MyFormatter : IDispatchMessageFormatter 
    { 
     IDispatchMessageFormatter original; 
     string replyAction; 
     public MyFormatter(IDispatchMessageFormatter original, string replyAction) 
     { 
      this.original = original; 
      this.replyAction = replyAction; 
     } 

     public void DeserializeRequest(Message message, object[] parameters) 
     { 
      this.original.DeserializeRequest(message, parameters); 
     } 

     public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) 
     { 
      ISerializable serializable = result as ISerializable; 
      if (serializable != null) 
      { 
       string json = JsonConvert.SerializeObject(serializable); 
       byte[] bytes = Encoding.UTF8.GetBytes(json); 
       var writer = new MyRawWriter(bytes); 
       Message reply = Message.CreateMessage(messageVersion, replyAction, writer); 
       reply.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw)); 
       return reply; 
      } 
      else 
      { 
       return this.original.SerializeReply(messageVersion, parameters, result); 
      } 
     } 

     class MyRawWriter : BodyWriter 
     { 
      byte[] data; 
      public MyRawWriter(byte[] data) 
       : base(true) 
      { 
       this.data = data; 
      } 

      protected override void OnWriteBodyContents(XmlDictionaryWriter writer) 
      { 
       writer.WriteStartElement("Binary"); 
       writer.WriteBase64(data, 0, data.Length); 
       writer.WriteEndElement(); 
      } 
     } 
    } 
    public class MyISerializableResponseJsonBehaviorAttribute : Attribute, IOperationBehavior 
    { 
     public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 
     { 
     } 

     public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 
     { 
      if (operationDescription.Messages.Count > 1) 
      { 
       dispatchOperation.Formatter = new MyFormatter(dispatchOperation.Formatter, operationDescription.Messages[1].Action); 
      } 
     } 

     public void Validate(OperationDescription operationDescription) 
     { 
      if (operationDescription.Messages.Count > 1) 
      { 
       var respMessage = operationDescription.Messages[1]; 
       if (respMessage.Body.Parts.Count > 0) 
       { 
        throw new InvalidOperationException("Cannot be used with out/ref parameters"); 
       } 
      } 

      var wga = operationDescription.Behaviors.Find<WebGetAttribute>(); 
      var wia = operationDescription.Behaviors.Find<WebInvokeAttribute>(); 
      WebMessageBodyStyle bodyStyle = WebMessageBodyStyle.Bare; // default 
      if (wga != null && wga.IsBodyStyleSetExplicitly) { 
       bodyStyle = wga.BodyStyle; 
      } 

      if (wia != null && wia.IsBodyStyleSetExplicitly) { 
       bodyStyle = wia.BodyStyle; 
      } 

      if (bodyStyle == WebMessageBodyStyle.Wrapped || bodyStyle == WebMessageBodyStyle.WrappedResponse) 
      { 
       throw new InvalidOperationException("This behavior can only be used with bare response style"); 
      } 
     } 
    } 
    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     host.AddServiceEndpoint(typeof(Service), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior()); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     WebClient c = new WebClient(); 
     Console.WriteLine(c.DownloadString(baseAddress + "/")); 
    } 
} 
+0

這個答案解決了我的問題。它應該被標記爲答案。 – AntonioJunior