【问题标题】:Why is my JSON invalid even though it looks correct?为什么我的 JSON 无效,即使它看起来正确?
【发布时间】:2019-09-10 19:47:18
【问题描述】:

我已经为此工作了很长一段时间,但我只是不明白为什么我的 JSON 无效......

JSONLint 显示此错误

    Error: Parse error on line 107:
...pair?",      "answer": "Yes, as long as the
----------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'

这是 JSON 的片段

{
    "tags": "already transferred",
    "question": "Can we transfer customers who have already been transferred previously? what is the dispo? warm transfer or already contacted?",
    "answer": "Yes, mark as already contacted."
},

{
    "tags": "secured debt",
    "question": "If customer only has secured debts, can we still offer credit repair?",
    "answer": "Yes, as long as they have at least $100 in secured/unsecured debt.
    "},




    {
        "tags": "state",
        "question": "Is the program state sensitive?",
        "answer": "Yes, each partner has particular states that they service. The script engine will only offer services when the state is valid for partner who has that service."
    },

它在说“是的,只要”的地方就失败了

JSON 是在 ColdFusion 中动态创建的。

<cfscript>faqCounter=1;</cfscript>
    <CFLOOP query="getFAQs">
         <cfoutput>
            {"tags":"#getFAQs.tags#","question":"#getFAQs.question#","answer":"#getFAQs.answer#"}<cfif faqCounter<getFAQCount.getFAQPertinentCount>,</cfif>
         </cfoutput>
        <cfscript>faqCounter++;</cfscript>
    </CFLOOP>

【问题讨论】:

  • JSON 字符串中不能有文字换行符,它应该是转义序列\n
  • @olegA \n 换行符就在此处的结束报价之前:有担保/无担保债务。"
  • 不要尝试通过分别填写每个属性来创建 JSON。对整个数组使用SerializeJSON() 函数。
  • 如果任何变量中包含双引号,您的代码也会失败,因为它们不会被转义。
  • 不要尝试在数据库中修补它。你的整个方法都是错误的。照我上面说的去做。

标签: javascript json coldfusion lucee


【解决方案1】:

引号“”中有一个 CRLF

"answer": "Yes, as long as they have at least $100 in secured/unsecured debt.
"},

【讨论】:

  • 你如何摆脱它?我试图序列化它,但它仍然向我显示该字符串是一个问题?它只是整个数组中的一个对象,当我删除它时,一切正常。
  • @OlegA 解决方案似乎是使用段落格式来删除字符串中的 CRLF:paragraphFormat(getFAQs.answer)。这个答案可以帮助你解决你的问题stackoverflow.com/questions/11330993/…
  • @pedrozopayares - 好主意,但这不是正确的功能。它设计用于在屏幕上显示输出。在某些情况下,它会将它们转换为 html &lt;p&gt;,这可能是不可取的。
【解决方案2】:

( 正如其他答案已经指出的那样,问题是未转义的新行,它破坏了 JSON。这是避免 DIY JSON 的原因之一。相反,使用内置函数 SerializeJSON() . )

Lucee 5.2.8.39+

尝试对JSON serialization-related settings in the Application.cfc 的新支持。新设置允许您覆盖 CF 用于序列化查询对象的奇怪默认设置:

// serialize queries as an array of structures AND
// preserves the column name case used in the sql
this.serialization.preserveCaseForStructKey = true;
this.serialization.serializeQueryAs = "struct";

现在您可以跳过所有的查询循环。只需执行查询并调用serializeJSON( yourQuery ),即可生成一个看起来非常合理的字符串,如下所示:

[
  {
    "answer": "Yes, mark as already contacted.",
    "tags": "already transferred",
    "question": "Can we transfer customers who have already been transferred previously? what is the dispo? warm transfer or already contacted?"
  },
  {
    "answer": "Yes, as long as they have at least $100 in secured/unsecured debt.  ",
    "tags": "secured debt",
    "question": "If customer only has secured debts, can we still offer credit repair?"
  }
]

Lucee 早期版本

对于早期版本,请执行@Barmar recommended。构建结构数组。然后使用serializeJSON 将数组转换为格式正确的 JSON 字符串。

Runnable Example

   <cfset yourArray = []>

   <cfloop query="getFAQs">
      <cfset yourArray.append( { "tags" : getFAQs.tags
                               , "question" : getFAQs.question
                               , "answer": getFAQs.answer
                             } )>    
   </cfloop>

   <cfset jsonString = serializeJSON( yourArray )>

如何删除新行?

生成“正确”的 JSON 字符串后,运行 replace() 并将 \n 替换为空字符串。

  <cfset jsonString  = replace(jsonString , "\n", "", "all")>

要永久删除它们,您必须首先找到将它们插入数据库的代码,并在那里进行修改。此外,更新任何现有的数据库记录以删除“\n”。

【讨论】:

    【解决方案3】:

    问题是字符串包含一个换行符作为文字,应该是\n。在大多数语言中,您都可以将数据过滤或序列化为 JSON,它会为您处理这些转换。

    考虑以下来自https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-s/serializejson.html的代码sn-ps

    此脚本利用 serializeJSON() 函数将数据转换为 JSON

    <cfscript>
           example = structnew();
           example.firstname = "Yes";
           example.lastname = "Man";
           // changing the default serialization by specifying the type of "firstname" as string
           metadata = {firstname: {type:"string"}};
           example.setMetadata(metadata);
           writeoutput(SerializeJSON(example));
    </cfscript>
    
    {"LASTNAME":"Man","FIRSTNAME":"Yes"}
    

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • @AlFoиceѫ 感谢您的建议,我原本打算将此答案添加为评论,但显然我没有足够的声誉来评论其他人的问题,将编辑我的回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多