提问人:Nate Anderson 提问时间:11/15/2023 最后编辑:Nate Anderson 更新时间:11/21/2023 访问量:54
使用带有 HTTP 的 WCF 将 C# 字典序列化为 JSON 对象
Serialize C# Dictionary as JSON object using WCF with HTTP
问:
我是具有 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做到这一点?
- 我可以看到这个问题/答案显示了如何使用 MVC / ASP.NET Core 更改 JsonSerializeSettings,但 WCF 是不同的,对吧?
我找到了许多有用的答案,但它们没有向我展示如何在WCF / HTTP上下文中执行此操作,因此REST响应会自动进行JSON序列化
- 我看到这个问题/答案使用
DataContractJsonSerializerSettings
,特别是UseSimpleDictionaryFormat = true
- 但是这个例子写到 一个 ;我在哪里指定在WCF项目中返回REST响应?在 Web.config 中?在 Global.asax.cs?
MemoryStream
- 但是这个例子写到 一个 ;我在哪里指定在WCF项目中返回REST响应?在 Web.config 中?在 Global.asax.cs?
- 此问题/答案使用自定义
[JsonConverter]
属性- 让我试试;我假设我可以尝试直接在我的属性上使用该属性
- 还有使用
[JsonExtensionData]
属性的问题/答案- 我也可以试试;我假设我可以尝试直接在我的属性上使用该属性
[JsonDictionary]
属性有什么作用?似乎在这里可能会有所帮助- 也许这个问题/答案正是我所需要的......
- (也仅供参考,只是将WCF服务上的这个问题与更一般的HTTP路由联系起来,因为我是WCF的新手......
- 以及其他类似问题
编辑
- 这是一个重复的问题
- 并在此处查看讨论
- 当我尝试指定如何反序列化 C# Date 对象时,我遇到了类似的问题
- 此处的 WCF 消息格式化程序帖子可能会有一些希望
答:
1赞
Nate Anderson
11/15/2023
#1
我尝试了 @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
,如下所示,所以我不喜欢它。
我更愿意按照@dbc的建议使用,但它没有暴露,正如@dbc所说!
所以就目前而言,这可能是最好的方法。如果没有其他建议,最终我会将问题作为重复或其他东西关闭......谢谢,@dbc!DataContractJsonSerializerSettings.UseSimpleDictionaryFormat
[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);
}
评论
ISerializable
的自定义类来执行此操作,第二个链接显示了如何使用WebOperationContext.Current.CreateTextResponse
手动写入响应来执行此操作ISerializable