【问题标题】:C# Parsing json that may have simple typesC#解析可能具有简单类型的json
【发布时间】:2017-10-02 21:30:24
【问题描述】:

我从 C# 调用返回 JSON 的 RESTful Web 服务。该服务可以返回一个任意的 Javascript 对象,我们在编译时不知道它的结构。

通常,它返回一个 JSON 对象,但也有返回简单字符串的情况。当我尝试反序列化简单字符串时,JSON.Net 会引发运行时错误。

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

抛出:

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

我阅读了以下问题的答案 Is this simple string considered valid JSON? 和共识似乎是返回一个简单的字符串作为 JSON 是合法的,但许多实现还不支持这一点。

这对 JSON.NET 来说是真的吗?处理反序列化可能包含简单类型而不仅仅是对象和数组的 JSON 的解决方法是什么?

这似乎工作正常,我错过了什么吗?

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

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

【问题讨论】:

  • 我相信你认为dynamic dyn = JsonConvert.DeserializeObject("just a string"); 是在传递一个字符串,但事实并非如此。试试dynamic dyn = JsonConvert.DeserializeObject("\"just a string\""); 看看结果如何:) 查看json spec 了解更多详情。
  • 是的,我明白了。您要发布作为答案吗?这就提出了一个不同的问题。看起来web服务应该在http正文中返回带引号的字符串,但是响应中没有双引号。
  • 您确定 Web 服务返回的是 JSON 类型而不是纯文本吗?
  • 是的,它正在返回 JSON。我将发布一个不同的问题,询问为什么 Java/Jersey 似乎没有引用简单的字符串 JSON 响应。

标签: c# json json.net


【解决方案1】:

@afuzzyllama 让我直接进入 cmets(如果他发布答案,我会很乐意接受!)。

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

失败,因为字符串不是有效的 JSON。字符串必须被引用,所以正确的应该是:

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

欲了解更多信息,请参阅http://www.json.org/

但是,这显然是 JAX-RS/Jersey Web 服务返回简单字符串的公认(和设计行为)。见https://stackoverflow.com/a/46535680/90236

【讨论】:

    【解决方案2】:

    查看以下调用:

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

    这不是反序列化"just a string",而是反序列化just a string(注意字符串被""包围)。

    如果我们查看spec for JSON,唯一不受"" 限制的有效字母字符序列是truefalsenull

    如果我们想反序列化一个字符串,我们需要确保它是规范定义的有效字符串。这应该是一个有效的反序列化调用:

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

    查看您之前的问题Java Jersey JSON service doesn't return quoted string?,我注意到您返回的是Object 类型:

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

    我对 Jersey 没有任何经验,但也许该框架无法解释通用的 Object。也许如果您使用String 返回类型,结果会有所不同?从该问题的公认答案来看,情况似乎并非如此?

    也许像下面这样的解决方案,添加"" 并更改返回类型,是否合适?

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

    结果应该是可反序列化的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-17
      • 1970-01-01
      • 1970-01-01
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多