C# Parsing json that may have simple types

大城市里の小女人 提交于 2019-12-11 07:07:07

问题


From C# I'm calling RESTful web service that returns JSON. The service can return an arbitrary Javascript object, we don't know its structure at compile time.

Usually, it returns a JSON object, but there are situations where it returns a simple string. JSON.Net throws a runtime error when I try to deserialize the simple string.

dynamic dyn = JsonConvert.DeserializeObject("just a string");            

throws:

Newtonsoft.Json.JsonReaderException was unhandled by user code
  HResult=-2146233088
  Message=Unexpected character encountered while parsing value: j. Path '', line 0, position 0.

I read the answers to Is this simple string considered valid JSON? and the consensus seems to be that returning a simple string as JSON is legal, but many implementations don't yet support this.

Is this true for JSON.NET? What are the workarounds to handle deserializing JSON that might contain simple types and not just objects and arrays?

This seems to work fine, am I missing something?

dynamic dyn;

dyn = GetObjectFromJSON("{ \"name\": \"john\", \"age\": 32 }");
Debug.WriteLine((string)Convert.ToString(dyn));

dyn = GetObjectFromJSON("[ \"a\", \"b\", \"c\" ]");
Debug.WriteLine((string)Convert.ToString(dyn));

dyn = GetObjectFromJSON("just a string");
Debug.WriteLine((string)Convert.ToString(dyn));

dyn = GetObjectFromJSON("35");
Debug.WriteLine((string)Convert.ToString(dyn));

dyn = GetObjectFromJSON("true");
Debug.WriteLine((string)Convert.ToString(dyn));

dyn = GetObjectFromJSON(null);
Debug.WriteLine((Object)dyn ?? "(null)");

and

private Object GetObjectFromJSON(string jsonString)
{
    if (String.IsNullOrEmpty(jsonString))
    {
        return null;
    }

    dynamic jsonResponse;
    jsonString = jsonString.Trim();
    if (jsonString.StartsWith("{") || jsonString.StartsWith("["))
    {
        // object or array
        jsonResponse = JsonConvert.DeserializeObject(jsonString);
    }
    else
    {
        // some literal value
        double d;
        bool b;
        if (Double.TryParse(jsonString, out d))
        {
            return d;
        }
        else if (bool.TryParse(jsonString, out b))
        {
            return b;
        }
        else
        {
            // not null, not an object, not an array, not a number, and not  a boolean, so it's a string
            jsonResponse = jsonString;
        }
    }
    return jsonResponse;
}

回答1:


@afuzzyllama set me straight in the comments (if he posts an answer, I'll happily accept it!).

dynamic dyn = JsonConvert.DeserializeObject("just a string");           

fails because the string is not valid JSON. Strings must be quoted, so to be correct this should be:

dynamic dyn = JsonConvert.DeserializeObject("\"just a string\"");           

For more info, see http://www.json.org/

But, this is apparently the accepted (and by design behavior) of JAX-RS/Jersey web services returning simple strings. See https://stackoverflow.com/a/46535680/90236




回答2:


Looking at the following call:

dynamic dyn = JsonConvert.DeserializeObject("just a string");           

This isn't deserializing "just a string" it is deserializing just a string (notice the string is surrounded by "").

If we look at the spec for JSON, the only valid alpha character sequences that are not bounded by "" are true, false, and null.

If we want to deserialize a string, we need to make sure it is a valid string as defined by the spec. This should be a valid deserialization call:

dynamic dyn = JsonConvert.DeserializeObject("\"just a string\"");           

Looking at your previous question Java Jersey JSON service doesn't return quoted string?, I noticed you are returning an Object type:

@GET
@Produces(MediaType.APPLICATION_JSON)
public Object interpretationJson() {                        
    String o = "a simple string";       
    return o;
}

I do not have any experience with Jersey, but perhaps the framework has trouble interpreting the generic Object. Perhaps if you used a String return type the results would be different? From the accepted answer from that question it does not seem to be the case?

Maybe a solution like the following, adding the "" and changing the return type, would be appropriate?

@GET
@Produces(MediaType.APPLICATION_JSON)
public String interpretationJson() {                        
    String o = "\"a simple string\"";       
    return o;
}

The result of that should be deserializable.



来源:https://stackoverflow.com/questions/46534008/c-sharp-parsing-json-that-may-have-simple-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!