我是使用 HTTP 路由的 WCF 服务的新手,但我的新项目使用 WCF。服务返回标有
[DataContract]
和 [DataMember]
属性 的对象,作为标有 [ServiceContract]
和 [OperationContract]
属性 的服务的一部分返回
我想返回一个带有
Dictionary<string, string>
的课程,如下所示:
var myObject = new Dictionary<string, string> { { "aKey", "aValue" } };
我希望它像这样 JSON 序列化:
{
"aKey": "aValue"
}
但是它的序列化是这样的:
[{
"Key": "aKey",
"Value": "aValue"
}]
如何使用 WCF + HTTP 做到这一点?
我找到了许多有用的答案,但它们没有向我展示如何在 WCF/HTTP 上下文中执行此操作,因此 REST 响应会自动 JSON 序列化
DataContractJsonSerializerSettings
,特别是UseSimpleDictionaryFormat = true
MemoryStream
;我在 WCF 项目中在哪里指定以便返回 REST 响应?在 Web.config 中?在 Global.asax.cs 中?[JsonConverter]
属性
[JsonExtensionData]
属性
[JsonDictionary]
属性有什么作用?看来这里可能会有帮助我尝试了@dbc第一个建议中的方法,通过创建我自己的类来扩展
ISerializable
。请参阅下面我修改后的课程。。现在这对我不起作用,永远不会调用 GetObjectData
方法,至少我的调试断点没有命中它。这表明我的项目可能没有使用默认序列化器(?)
[Serializable]
public class SerializableDictionary<TKey, TValue> : ISerializable, IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
{
//https://stackoverflow.com/a/7590189/1175496
private Dictionary<TKey, TValue> _Dictionary;
public SerializableDictionary(Dictionary<TKey, TValue> dictionary)
{
_Dictionary = dictionary;
}
public SerializableDictionary() : this(new Dictionary<TKey, TValue>()) { }
public SerializableDictionary(SerializationInfo info, StreamingContext context) : this(new Dictionary<TKey, TValue>()) {
/* no deserializing */
//https://stackoverflow.com/a/47187399/1175496
}
public TValue this[TKey key]
{
get { return _Dictionary[key]; }
set { _Dictionary[key] = value; }
}
public ICollection<TKey> Keys => this._Dictionary.Keys;
public ICollection<TValue> Values => this._Dictionary.Values;
public int Count => this._Dictionary.Count;
public bool IsReadOnly => true;
public void Add(TKey key, TValue value)
{
_Dictionary.Add(key, value);
}
public void Add(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public bool ContainsKey(TKey key)
{
throw new NotImplementedException();
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _Dictionary.GetEnumerator();
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (TKey key in _Dictionary.Keys)
info.AddValue(key.ToString(), _Dictionary[key]);
}
public bool Remove(TKey key)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public bool TryGetValue(TKey key, out TValue value)
{
return this._Dictionary.TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this._Dictionary.GetEnumerator();
}
}
相反,我尝试了@dbc第二个建议中的方法,并且它起作用了。它依赖于手动返回
System.ServiceModel.Channels.Message
,如下所示所以我不喜欢它。
我更喜欢使用
DataContractJsonSerializerSettings.UseSimpleDictionaryFormat
,正如 @dbc 建议的那样,但它没有暴露,正如 @dbc 所说!)。
所以就目前而言,这可能是最好的办法。如果没有其他建议,最终我会将问题作为重复或其他问题关闭...谢谢,@dbc!
[OperationContract]
[WebGet( UriTemplate = "/getResponse", ResponseFormat = WebMessageFormat.Json)]
public Message GetResponse()
{
string json = JsonConvert.SerializeObject(new Dictionary<string, string> { { "key", "value" } });
return WebOperationContext.Current.CreateTextResponse(json, "application/json; charset=utf-8", Encoding.UTF8);
}