0

I created a service to do database lookup and return result as JSON, using Nancy. Here is test code:

using (var dt = new DataTable("MyData"))
{
    dt.Columns.Add("id");
    dt.Columns.Add("password");
    dt.Columns.Add("body", System.Type.GetType("System.String"));
    dt.Columns.Add("balance", System.Type.GetType("System.Double"));
    dt.Rows.Add(uid, pwd, "Some useful content", 33.75);
    dt.Rows.Add(uid, pwd, "More useful content", 128.55);
    if (dotNetDataTable)
        json = JsonConvert.SerializeObject(dt, new Serialization.DataTableConverter());
    else
        json = JsonConvert.SerializeObject(dt);
    json = "{\"status\":\"success\",\"data\":" + json + "}";
    return Response.AsJson(json);
}

Interrupting process just before return, and polling value of json, I get:

"{\"status\":\"success\",\"data\":[{\"id\":\"RMittelman\",\"password\":\"Password\",\"body\":\"Some useful content\",\"balance\":33.75},{\"id\":\"RMittelman\",\"password\":\"Password\",\"body\":\"More useful content\",\"balance\":128.55}]}"

This seems correct in immediate window. When I receive data, and interrupt the process, I get this in the client immediate window:

"\"{\\\"status\\\":\\\"success\\\",\\\"data\\\":[{\\\"id\\\":\\\"RMittelman\\\",\\\"password\\\":\\\"Password\\\",\\\"body\\\":\\\"Some useful content\\\",\\\"balance\\\":33.75},{\\\"id\\\":\\\"RMittelman\\\",\\\"password\\\":\\\"Password\\\",\\\"body\\\":\\\"More useful content\\\",\\\"balance\\\":128.55}]}\""

Which as you can see contains extra leading and trailing quotes, and a bunch of extra backslashes. The JSON will not deserialize. Here is the result shown in client's text box:

json result:
"{\"status\":\"success\",\"data\":
[{\"id\":\"RMittelman\",\"password\":\"Password\",\"body\":\"Some useful content\",\"balance\":33.75},
{\"id\":\"RMittelman\",\"password\":\"Password\",\"body\":\"More useful content\",\"balance\":128.55}]}"

Unexpected JSON token when reading DataTable. Expected StartArray, got String. Path '', line 1, position 240.

If I programmatically remove leading and trailing quotes, and all backslashes, it works fine. Here is the code I use in client to get the data:

string GET(string url)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    try
    {
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
            string responseText = reader.ReadToEnd();
            isError = false;
            return responseText;
        }
    }
    catch (WebException ex)
    {
        isError = true;
        WebResponse errorResponse = ex.Response;
        if (errorResponse == null)
            return ex.Message;
        using (Stream responseStream = errorResponse.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
            return errorText;
        }
        throw;
    }
}

So question is, why does it look ok before sending, but contain all the junk after sending?

dbc
  • 104,963
  • 20
  • 228
  • 340
RMittelman
  • 319
  • 3
  • 16
  • 2
    Looks like you are double-encoding your JSON string somewhere along the way. Remove one level of JSON encoding. – Tomalak Apr 15 '16 at 15:49
  • This is confusing to me. The first immediate window result, just before returning the original JSON string from the service looks correct. I know it shows quotes and slashes, but that's an immediate window thing, right? It's the second one, after receiving, that has all the extra digits. I didn't write the .Net code to post and receive, got it off google. But it doesn't seem to contain any JSON encoding. I'm at a loss to figure out why it looks ok just before returning response, but has extra garbage after receiving. Is there maybe some kind of character-encoding thing going on? – RMittelman Apr 15 '16 at 15:57
  • You're double-serializing your JSON. (Serializing the class to JSON, then serializing the JSON as a string literal.) See maybe https://stackoverflow.com/questions/7597035/returning-a-string-containing-valid-json-with-nancy or https://stackoverflow.com/questions/33983600/why-can-i-not-register-a-custom-json-net-implementation-in-nancy – dbc Apr 15 '16 at 16:05
  • 1
    It's not garbage, that's what double-encoding looks like. Just like `"&"` becomes `"&"` in HTML and `"&"` in double-encoded HTML. It's very likely that the .NET web method already is configured to return JSON. Therefore you don't need to do any manual JSON serialization, just return the data itself. – Tomalak Apr 15 '16 at 16:23
  • Thanks @Tomalak. I was doing: json=JsonConvert.SerializeObject, then: Return Response.AsJson(json). `code` There's your double serializing. First time with json. Rookie mistake. I'd give you credit if I knew how to credit comments. – RMittelman Apr 15 '16 at 19:08
  • Thanks for the clarification, @dbc. That helped a lot. – RMittelman Apr 15 '16 at 19:31
  • Never mind, I merely saw what's wrong, you fixed it yourself. Write an answer of your own that outlines the mistake, I'll upvote. – Tomalak Apr 15 '16 at 20:58

1 Answers1

3

JSON was getting double-encoded. Code was:

json=JsonConvert.SerializeObject(dataTable);

then

return Response.AsJson(json);

Changed it to:

return (Response)json;

and the problem went away. Thanks everybody for your input!

RMittelman
  • 319
  • 3
  • 16