Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
370 views
in Technique[技术] by (71.8m points)

c# - How to return a Dictionary of custom type values as a regular JSON object from a WCF REST method?

Let's say I've got a custom type that looks like this:

[DataContract]
public class CompositeType
{
    [DataMember]
    public bool HasPaid
    {
        get;
        set;
    }

    [DataMember]
    public string Owner
    {
        get;
        set;
    }
}

and a WCF REST interface that looks like this:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    Dictionary<string, CompositeType> GetDict();
}

then how do I get my implementation of that method to return a JSON object that looks like this...

{"fred":{"HasPaid":false,"Owner":"Fred Millhouse"},"joe":{"HasPaid":false,"Owner":"Joe McWirter"},"bob":{"HasPaid":true,"Owner":"Bob Smith"}}

I do not want it to look like this:

[{"Key":"fred","Value":{"HasPaid":false,"Owner":"Fred Millhouse"}},{"Key":"joe","Value":{"HasPaid":false,"Owner":"Joe McWirter"}},{"Key":"bob","Value":{"HasPaid":true,"Owner":"Bob Smith"}}]

Ideally I would prefer not to have to alter the return type of the method.

I have tried many different approaches but cannot find a solution that works. Annoyingly, it is easy to produce the right-shaped JSON object structure in one line with Newtonsoft.Json:

string json = JsonConvert.SerializeObject(dict);

where dict is defined as:

Dictionary<string, CompositeType> dict = new Dictionary<string, CompositeType>();
dict.Add("fred", new CompositeType { HasPaid = false, Owner = "Fred Millhouse" });
dict.Add("joe", new CompositeType { HasPaid = false, Owner = "Joe McWirter" });
dict.Add("bob", new CompositeType { HasPaid = true, Owner = "Bob Smith" });

but I do not want to return a string from my WCF method. This is because it conceals the real type being returned; and also because WCF serializes the string as well, resulting in escaped double quotes and other ugliness that makes it harder for non-.Net REST clients to parse.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a partial solution in response to comments by @dbc. It results in the right-shaped JSON structure of this...

{"fred":{"HasPaid":false,"Owner":"Fred Millhouse"},"joe":{"HasPaid":false,"Owner":"Joe McWirter"},"bob":{"HasPaid":true,"Owner":"Bob Smith"}}

but unfortunately involves having to change the return type of the method to Message. The interface becomes:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    Message GetDict();
}

and the implementation becomes:

using Newtonsoft.Json;
...
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public Message GetDict()
{
    Dictionary<string, CompositeType> dict = new Dictionary<string, CompositeType>();
    dict.Add("fred", new CompositeType { HasPaid = false, Owner = "Fred Millhouse" });
    dict.Add("joe", new CompositeType { HasPaid = false, Owner = "Joe McWirter" });
    dict.Add("bob", new CompositeType { HasPaid = true, Owner = "Bob Smith" });

    string json = JsonConvert.SerializeObject(dict);
    return WebOperationContext.Current.CreateTextResponse(json, "application/json; charset=utf-8", Encoding.UTF8);
}

One useful feature to note is that, unlike when returning Stream, you can view the JSON easily in your web browser when you visit the REST method's URI.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...