使用 WCF 和 HTTP 将 C# 字典序列化为 JSON 对象

问题描述 投票:0回答:1

我是使用 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 序列化

c# json wcf
1个回答
0
投票

我尝试了@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);

    }
© www.soinside.com 2019 - 2024. All rights reserved.