为什么我的服务器无法解析此JSON代码?

时间:2017-02-15 00:34:31

标签: ruby-on-rails json ruby parsing

我的服务器成功解析了一些JSON代码(因为丢失了)。我保留了结构,只是添加/更改了一些数据条目。现在,当我尝试解析它时,我的代码返回了以下错误:

JSON::ParserError in Static#testing4
Showing /home/user/website/app/views/static/testing4.html.erb where line #44 raised:

399: unexpected token at '  {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
'

这是我的代码。 问题是开头的{"1":[由于某种原因未被解析。此视图没有关联的控制器操作。

<!--testing4.html.erb-->
<%
require 'json'
require 'pp'

json = <<END_OF_JSON
{
    "1": [
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
END_OF_JSON


%>
<%= obj = JSON.parse(json) %>

尝试输出它而不解析它会产生以下结果:

<%
require 'json'
require 'pp'

json = <<END_OF_JSON
{
    "1": [
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
END_OF_JSON


%>
PUTS: <%= puts json %><br>
PP: <%= pp json %>


---output---

PUTS: 
PP: { "1": [   {     "title": "TITLE1",     "capital": "Rome",     "length": 2.7,     "date": "2017-1-2",     "tags": [       "Culture"     ] }], "2": [   {     "title": "TITLE2",     "capital": "Paris",     "age": 1.2,     "date": "2017-2-1",     "tags": [       "Culture"     ] }] }

1 个答案:

答案 0 :(得分:2)

  

jsonlint不可靠,还是还有其他事情发生?

jsonlint是可靠的,ruby在解析你发布的json方面没有问题:

require 'json'
require 'pp' 

json = <<END_OF_JSON
{  
    "1": [
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
END_OF_JSON

obj = JSON.parse(json)
pp obj

--output:--

{"1"=>
  [{"title"=>"TITLE1",
    "capital"=>"Rome",
    "length"=>2.7,
    "date"=>"2017-1-2",
    "tags"=>["Culture"]}],
 "2"=>
  [{"title"=>"TITLE2",
    "capital"=>"Paris",
    "age"=>1.2,
    "date"=>"2017-2-1",
    "tags"=>["Culture"]}]}

但是,如果您查看文件或输出字符串,则非打印字符不一定是可见的:

test = "\001hello"
puts test
p test

--output:--
hello
"\u0001hello"

这里你会得到一个解析错误:

require 'json'
require 'pp' 

json = <<END_OF_JSON
{
    \001"1": [1, 2, 3]
}
END_OF_JSON

obj = JSON.parse(json)

即使输出时json看起来很好:

require 'json'
require 'pp' 

json = <<END_OF_JSON
{
    \001"1": [1, 2, 3]
}
END_OF_JSON

puts json
obj = JSON.parse(json)

--output:--
{
    "1": [1, 2, 3]
}

/Users/7stud/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/json/common.rb:156:in `parse': 784: unexpected token at '{ (JSON::ParserError)
    "1": [1, 2, 3]
}
'
    from /Users/7stud/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/json/common.rb:156:in `parse'
    from 1.rb:11:in `<main>'

因此,您可能希望从文件中读取json,然后使用p输出文本,然后检查文本是否有任何奇怪的字符。

另外,请复制并粘贴完整的错误消息 - 不要输入您认为错误消息的内容,然后声明这是您的程序生成的内容。我可以复制你用这个json发布的错误信息:

json = <<END_OF_JSON
(code) = {
    "1": [
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
END_OF_JSON

obj = JSON.parse(json)

--output:--
`parse': 784: unexpected token at '(code) = { (JSON::ParserError)
    "1": [
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
'
    from /Users/7stud/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/json/common.rb:156:in `parse'
    from 1.rb:29:in `<main>'

对评论1的回复

错误消息包含rails正在看到的json,这里是:

399: unexpected token at '  {   #<===Opening brace, which starts a javascript object.
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],   #<====First, a closing brace that ends the javascript object, followed by a closing bracket, ending what?
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ] 
    }]
}

如果我将无效的json放在rails视图中:

<%
json = <<END_OF_JSON 
{
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
END_OF_JSON

obj = JSON.parse(json)
%>

...然后在我的浏览器中输入将显示该视图的路径,这是我在浏览器中收到的错误消息:

Showing /Users/7stud/rails_projects/test4/app/views/users/index.html.erb where line #27 raised:

784: unexpected token at '{
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
    }],
    "2": [
      {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }]
}
'

看起来很熟悉?如果你在json的其他地方有错误,就像这里:

<%
json = <<END_OF_JSON
{    
  "1": [
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
      }
  ],
  "2":   #<====Missing opening bracket
    {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }
  ]
}
END_OF_JSON

obj = JSON.parse(json)
%>

然后您会在浏览器中看到如下错误消息:

Showing /Users/7stud/rails_projects/test4/app/views/users/index.html.erb where line #32 raised:

784: unexpected token at '{    
  "1": [   #<===Note the presence of "1": [, unlike in your error message.
      {
        "title": "TITLE1",
        "capital": "Rome",
        "length": 2.7,
        "date": "2017-1-2",
        "tags": [
          "Culture"
        ]
      }
  ],
  "2":    
    {
        "title": "TITLE2",
        "capital": "Paris",
        "age": 1.2,
        "date": "2017-2-1",
        "tags": [
          "Culture"
        ]
    }
  ]
}
'

因此,导轨看到的json中不存在"1": [。如果您需要更多帮助,则需要复制并粘贴以下代码:

  1. 您的控制器和行动。
  2. 行动的观点。
  3. 对评论2的回复

    rails视图能够呈现以下json而不会出现错误(删除所有空格):

    <!--testing4.html.erb-->
    <%
    require 'json'
    require 'pp'
    
    json = <<END_OF_JSON
    {
      "1": [{"title": "TITLE1", "capital": "Rome", "length": 2.7, "date": "2017-1-2", "tags": ["Culture"]}],
      "2": [{"title": "TITLE2", "capital": "Paris", "age": 1.2, "date": "2017-2-1", "tags": ["Culture"]}]
    }
    END_OF_JSON
    
    %>
    <%= obj = JSON.parse(json) %>
    

    并且,rails视图能够呈现以下json而不会出现错误(所有空格都重新添加):

    <!--testing4.html.erb-->
    <%
    require 'json'
    require 'pp'
    
    json = <<END_OF_JSON
    {
         "1": [
           {
             "title": "TITLE1", 
             "capital": "Rome", 
             "length": 2.7, 
             "date": "2017-1-2", 
             "tags": [
               "Culture"
             ]
         }],
         "2": [
           {
             "title": "TITLE2", 
             "capital": "Paris", 
             "age": 1.2, "date": 
             "2017-2-1", 
             "tags": [
               "Culture"
             ]
         }]
    }
    END_OF_JSON
    
    %>
    <%= obj = JSON.parse(json) %>
    

    但是,由于某种原因,rails视图无法呈现您的json:

    <!--testing4.html.erb-->
    <%
    require 'json'
    require 'pp'
    
    json = <<END_OF_JSON
    {
        "1": [
          {
            "title": "TITLE1",
            "capital": "Rome",
            "length": 2.7,
            "date": "2017-1-2",
            "tags": [
              "Culture"
            ]
        }],
        "2": [
          {
            "title": "TITLE2",
            "capital": "Paris",
            "age": 1.2,
            "date": "2017-2-1",
            "tags": [
              "Culture"
            ]
        }]
    }
    END_OF_JSON
    
    
    %>
    <%= obj = JSON.parse(json) %>
    

    经过一些进一步调查后,你的json混合了ascii空格(十六进制表示法为20)和一种称为EM SPACE U+2003 e2 80 83 EM SPACE的UTF-8空格字符在UTF-8)。你的json中的第一个{ "1": [   { ^ | Right there 出现在这里:

    7b

    ...巧合的是,rails错误信息正在切断你的json。紧接在该开头括号(十六进制表示法中的20)之前是ascii空格(十六进制表示法中的EM SPACE),ascii空格前面的字符是一个三字节UTF-8字符,称为{{1 (U + 2003,UTF-8中的e2 80 83)。以UTF-8编码编码的字符应该是合法的json。 jsonlint接受EM SPACE,但是在它上面有阻塞。

    作为问题的一个简短示例,以下javascript数组在每个逗号后面都有EM SPACE

    <!--testing4.html.erb-->  
    <%
    json = "[1, 2, 3]"
    %>
    
    <%= obj = JSON.parse(json) %>
    

    以下是我浏览器中的错误:

    419: unexpected token at ' 2, 3]'
    

    导轨错误会将json切断到第一个EM SPACE

    事实证明,虽然json中允许使用UTF-8字符,但json术语之间只允许使用几个ascii空格字符 - 而不仅仅是任何UTF-8字符。见RFC 7159。在json术语之间使用EM SPACE在概念上等同于在术语之间使用z。因此,包含EM SPACE个字符的json是非法的json。在字符串中使用EM SPACE是合法的,但不能在json术语之间使用。

    以下jsonlinter报告带有EM SPACE字符的json无效:

    http://www.freeformatter.com/json-validator.html

    似乎有些jsonlinters比其他人更可靠。

    解决方案:

    您可以使用gsub()将所有EM SPACE字符替换为ascii空格:

    ...
    ...
    END_OF_JSON
    
    clean_json = json.gsub("\u2003", ' ')
    
    %>
    <%= obj = JSON.parse(clean_json) %>
    

    如果你从某个地方的服务中得到了json,你应该给他们发一封电子邮件,让他们知道他们发出的json是非法的。