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

Serialize C# Dictionary as JSON object using WCF with HTTP

提问人:Nate Anderson 提问时间:11/15/2023 最后编辑:Nate Anderson 更新时间:11/21/2023 访问量:54

问:

我是具有 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赞 dbc 11/15/2023
是否 ASP.NET WCF 将字典转换为 JSON,省略“键”和“值”标记,或者如何从 WCF REST 方法返回自定义类型值的字典作为常规 JSON 对象? 回答您的问题?
1赞 Nate Anderson 11/15/2023
是的,如果我理解,他们会给我解决方法,让我试试那些......也许我可以将我的问题标记为重复。第一个链接显示了如何通过创建扩展 ISerializable 的自定义类来执行此操作,第二个链接显示了如何使用 WebOperationContext.Current.CreateTextResponse 手动写入响应来执行此操作
0赞 Nate Anderson 11/15/2023
感谢您的第二个建议@dbc奏效。我不确定为什么第一个建议不起作用(我有点喜欢第一个建议......)也许我的项目没有配置为以第一个建议所需的方式使用。谢谢,我可以把这个问题作为重复或其他东西来结束,或者如果你回答,我会给你信用!谢谢ISerializable

答:

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);

    }