JSON response from WCF escapes name values -
i trying return dictionary wcf rest service json object. want format {"key": "value"} have created own class described here , here.
the service method works, sort of. problem key names escaped. example, if dictionary contains "hello world": 100, {"hello_x0020_world":100}. escapes other characters %, etc.
is there way can tell serialization not escape names way? using xml rules don't (necessarily) apply json.
my serializable class:
[serializable] public class jsondictionary : iserializable { private dictionary<string, object> _dictionary; public jsondictionary() { _dictionary = new dictionary<string, object>(); } public jsondictionary(serializationinfo info, streamingcontext context) { _dictionary = new dictionary<string, object>(); serializationinfoenumerator enumerator = info.getenumerator(); while (enumerator.movenext()) { _dictionary.add(enumerator.name, enumerator.value); } } public object this[string key] { { return _dictionary[key]; } set { _dictionary[key] = value; } } public void add(string key, object value) { _dictionary.add(key, value); } public bool containskey(string key) { return _dictionary.containskey(key); } public void getobjectdata(serializationinfo info, streamingcontext context) { foreach (string key in _dictionary.keys) info.addvalue(key, _dictionary[key], _dictionary[key] == null ? typeof(object) : _dictionary[key].gettype()); } }
my service function definition:
[webget(uritemplate = "", responseformat = webmessageformat.json)] public jsondictionary getcollection() { jsondictionary dict = new jsondictionary(); dict.add("hello world", 100); return dict; }
the datacontractjsonserializer
used default in wcf uses xml-to-json mapping causes issues, 1 see in iserializable
types. can, however, use custom formatter change how response serialized. in example below, i'm using json.net deals iserializable
objects "correctly".
public class stackoverflow_16674152 { [serializable] public class jsondictionary : iserializable { private dictionary<string, object> _dictionary; public jsondictionary() { _dictionary = new dictionary<string, object>(); } public jsondictionary(serializationinfo info, streamingcontext context) { _dictionary = new dictionary<string, object>(); serializationinfoenumerator enumerator = info.getenumerator(); while (enumerator.movenext()) { _dictionary.add(enumerator.name, enumerator.value); } } public object this[string key] { { return _dictionary[key]; } set { _dictionary[key] = value; } } public void add(string key, object value) { _dictionary.add(key, value); } public bool containskey(string key) { return _dictionary.containskey(key); } public void getobjectdata(serializationinfo info, streamingcontext context) { foreach (string key in _dictionary.keys) info.addvalue(key, _dictionary[key], _dictionary[key] == null ? typeof(object) : _dictionary[key].gettype()); } } [servicecontract] public class service { [webget(uritemplate = "", responseformat = webmessageformat.json)] [myiserializableresponsejsonbehavior] public jsondictionary getcollection() { jsondictionary dict = new jsondictionary(); dict.add("hello world", 100); return dict; } } public class myformatter : idispatchmessageformatter { idispatchmessageformatter original; string replyaction; public myformatter(idispatchmessageformatter original, string replyaction) { this.original = original; this.replyaction = replyaction; } public void deserializerequest(message message, object[] parameters) { this.original.deserializerequest(message, parameters); } public message serializereply(messageversion messageversion, object[] parameters, object result) { iserializable serializable = result iserializable; if (serializable != null) { string json = jsonconvert.serializeobject(serializable); byte[] bytes = encoding.utf8.getbytes(json); var writer = new myrawwriter(bytes); message reply = message.createmessage(messageversion, replyaction, writer); reply.properties.add(webbodyformatmessageproperty.name, new webbodyformatmessageproperty(webcontentformat.raw)); return reply; } else { return this.original.serializereply(messageversion, parameters, result); } } class myrawwriter : bodywriter { byte[] data; public myrawwriter(byte[] data) : base(true) { this.data = data; } protected override void onwritebodycontents(xmldictionarywriter writer) { writer.writestartelement("binary"); writer.writebase64(data, 0, data.length); writer.writeendelement(); } } } public class myiserializableresponsejsonbehaviorattribute : attribute, ioperationbehavior { public void addbindingparameters(operationdescription operationdescription, bindingparametercollection bindingparameters) { } public void applyclientbehavior(operationdescription operationdescription, clientoperation clientoperation) { } public void applydispatchbehavior(operationdescription operationdescription, dispatchoperation dispatchoperation) { if (operationdescription.messages.count > 1) { dispatchoperation.formatter = new myformatter(dispatchoperation.formatter, operationdescription.messages[1].action); } } public void validate(operationdescription operationdescription) { if (operationdescription.messages.count > 1) { var respmessage = operationdescription.messages[1]; if (respmessage.body.parts.count > 0) { throw new invalidoperationexception("cannot used out/ref parameters"); } } var wga = operationdescription.behaviors.find<webgetattribute>(); var wia = operationdescription.behaviors.find<webinvokeattribute>(); webmessagebodystyle bodystyle = webmessagebodystyle.bare; // default if (wga != null && wga.isbodystylesetexplicitly) { bodystyle = wga.bodystyle; } if (wia != null && wia.isbodystylesetexplicitly) { bodystyle = wia.bodystyle; } if (bodystyle == webmessagebodystyle.wrapped || bodystyle == webmessagebodystyle.wrappedresponse) { throw new invalidoperationexception("this behavior can used bare response style"); } } } public static void test() { string baseaddress = "http://" + environment.machinename + ":8000/service"; servicehost host = new servicehost(typeof(service), new uri(baseaddress)); host.addserviceendpoint(typeof(service), new webhttpbinding(), "").behaviors.add(new webhttpbehavior()); host.open(); console.writeline("host opened"); webclient c = new webclient(); console.writeline(c.downloadstring(baseaddress + "/")); } }
Comments
Post a Comment