【问题标题】:JSON parsing error syntax error unexpected end of inputJSON解析错误语法错误意外结束输入
【发布时间】:2014-01-16 14:53:25
【问题描述】:

我得到以下代码

function pushJsonData(productName) {
    $.ajax({
        url: "/knockout/SaveProduct",
        type: "POST",
        contentType: "application/json",
        dataType: "json",
        data: " { \"Name\" : \"AA\" } ",
        async: false,
        success: function () {
            loadJsonData();   
        },
        error: function (jqXHR, textStatus, errorThrown) {
          alert(textStatus + " in pushJsonData: " + errorThrown + " " + jqXHR);
        }
    });
}

请注意,我对数据值进行了硬编码。数据被很好地推入数据库。但是,我不断收到错误

解析错误语法错误意外结束输入

我确信我的数据是正确的 JSON 语法。当我在 Chrome 网络检查器上检查时,saveProduct 请求显示数据是正确的。

{ "Name": "AA" }

此 POST 请求没有响应。所以我对解析错误的来源一无所知。我尝试使用 FireFox 浏览器。同样的事情发生了。

谁能给出一些关于哪里出了问题的想法?

谢谢,

附: 这是控制器代码

namespace MvcApplJSON.Controllers
{
    public class KnockoutController : Controller
    {
        //
        // GET: /Knockout/

        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public JsonResult GetProductList()
        {
            var model = new List<Product>();
            try
            {
                using (var db = new KOEntities())
                {
                    var product = from p in db.Products orderby p.Name select p;
                    model = product.ToList();
                }
            }
            catch (Exception ex)
            { throw ex; }
            return Json(model, JsonRequestBehavior.AllowGet);
        }
        [HttpPost]
        public void SaveProduct (Product product)
        {
            using (var db = new KOEntities())
            {
                db.Products.Add(new Product { Name = product.Name, DateCreated = DateTime.Now });
                db.SaveChanges();
            }
        }
    }
}

【问题讨论】:

  • " { \"Name\" : \"AA\" } " -> " { 'Name' : 'AA' } " 在 json 对象中 "' 之间存在差异
  • 是的,您的第二个示例生成无效的 JSON。单引号不是有效的 JSON!
  • @DarinDimitrov 这也适用于我所看到的(您可以在 jsonviewer.stack.hu 上尝试),但您不能将字符串作为对象发送(如果您没有该对象字符串名称可用)。所以最后:你是对的
  • 这个错误出现在客户端还是服务器端?
  • 您刚刚失去了 Internet 连接。就是这样。

标签: jquery ajax json asp.net-mvc-4 knockout.js


【解决方案1】:

我不能确定问题是什么。可能是一些不好的角色,可能是你在开头和结尾留下的空格,不知道。

无论如何,您不应该像以前那样将 JSON 硬编码为字符串。相反,将 JSON 数据发送到服务器的正确方法是使用 JSON 序列化程序:

data: JSON.stringify({ name : "AA" }),

现在在服务器上还要确保你有正确的视图模型来接收这个输入:

public class UserViewModel
{
    public string Name { get; set; }
}

以及对应的动作:

[HttpPost]
public ActionResult SaveProduct(UserViewModel model)
{
    ...
}

现在还有一件事。您已指定dataType: 'json'。这意味着您期望服务器将返回 JSON 结果。控制器操作必须返回 JSON。如果您的控制器操作返回一个视图,这可以解释您遇到的错误。当 jQuery 尝试解析来自服务器的响应时:

[HttpPost]
public ActionResult SaveProduct(UserViewModel model)
{
    ...
    return Json(new { Foo = "bar" });
}

话虽如此,在大多数情况下,当向 ASP.NET MVC 控制器操作发出 AJAX 请求时,通常不需要设置 dataType 属性。这样做的原因是因为当你返回一些特定的ActionResult(例如ViewResultJsonResult)时,框架会自动设置正确的Content-Type 响应HTTP 头。然后,jQuery 将使用此标头解析响应并将其作为参数提供给已解析的成功回调。

我怀疑您在这里遇到的问题是您的服务器没有返回有效的 JSON。它要么返回一些 ViewResult 或 PartialViewResult,要么您尝试在控制器操作中手动制作一些损坏的 JSON(显然您不应该这样做,而是使用 JsonResult 代替)。

我刚刚注意到的另一件事:

async: false,

请避免将此属性设置为 false。如果您将此属性设置为false,您将在整个请求执行期间冻结客户端浏览器。在这种情况下,您可以提出一个正常的请求。如果您想使用 AJAX,请从异步事件和回调的角度开始考虑。

【讨论】:

  • 嗨,达林,感谢您的快速回复。我试图将您的代码粘贴到我的代码中,以替换我拥有的代码。但我得到了完全相同的错误。我可以看到数据被推送到数据库中。我可以选择验证。我正在使用带有 knockout.js 的 MS ASP.NET MVC4。可以找出哪个部分在抱怨这个错误。
  • 也许错误在您在success 回调中调用的loadJsonData 函数内部,与AJAX 请求本身无关?您究竟在哪里/何时看到此错误?使用 FireBug 或 Chrome 开发者工具栏的Network 选项卡来检查 AJAX 请求并查看服务器是否返回 JSON 响应。服务器的确切响应是什么?您的 success 回调不接受任何参数。这是为什么?您的 SaveProduct 控制器操作是否返回 JsonResult?我怀疑您将其声明为void。请仔细阅读我的整个答案。
  • 好的,但您没有回答我在上一条评论中的其他问题。我会重复一遍:服务器的确切响应是什么?您的 success 回调不接受任何参数。这是为什么?您的SaveProduct 控制器操作是否返回JsonResult?我怀疑您将其声明为void
  • 哥们,你还在看我的回答吗???我强调的一件事是你的控制器操作应该返回一个JsonResult。不存在返回void 的控制器操作。您已指定 dataType: 'json',因此返回 JSON。而已。至于这个控制器操作应该采用什么参数,那么,从您发送的 JSON ({"Name":"AA"}) 中,它应该是一个具有字符串类型的 Name 属性的类。这一切都已经在我的回答中体现出来了。 请仔细阅读。我在回答中为您提供了解决此问题所需的一切
  • 所以,是的,修改你的动作签名看起来像这样:[HttpPost] public ActionResult SaveProduct (Product product) { ... return Json(new { success = true }); }。或者,如果您不想返回 JSON,请从您的 AJAX 请求中删除此 dataType: 'json' 属性。在这种情况下,您可以简单地返回状态代码 201(使用空响应正文创建):return new HttpStatusCodeResult(201);
【解决方案2】:

我正在使用节点 http 请求并监听 data 事件。该事件只是将数据临时放入缓冲区,因此无法获得完整的 JSON。要解决此问题,必须将每个 data 事件附加到一个变量。可能会帮助某人 (http://nodejs.org/api/http.html)。

【讨论】:

    【解决方案3】:

    不要返回空 Json

    在我的情况下,我在 .Net Core Web API 项目中返回 Empty Json String。

    所以我改变了我的代码

    来自

     return Ok();
    

    收件人

     return Ok("Done");
    

    看来你必须返回一些字符串或对象。

    希望这会有所帮助。

    【讨论】:

    • 谢谢,让我来:'return Request.CreateResponse(HttpStatusCode.OK, "Done");'
    【解决方案4】:

    对我来说,问题是由于名称/值对的单引号引起的... 数据:“{'Name':'AA'}”

    一旦我将它更改为名称/值对的双引号,它就可以正常工作... 数据:'{“名称”:“AA”}' 或者像这样... 数据:"{\"姓名\":\"AA\"}"

    【讨论】:

      【解决方案5】:

      可能会有用。

      方法参数名称应该和JSON一样

      它会正常工作

      C#

      public ActionResult GetMTypes(int id)
      

      JS

       var params = { id: modelId  };
                       var url = '@Url.Action("GetMTypes", "MaintenanceTypes")';
                       $.ajax({
                           type: "POST",
                           url: url,
                           contentType: "application/json; charset=utf-8",
                           dataType: "json",
                           data: JSON.stringify(params),
      

      它不会正常工作

      C#

      public ActionResult GetMTypes(int modelId)
      

      JS

       var params = { id: modelId  };
                       var url = '@Url.Action("GetMTypes", "MaintenanceTypes")';
                       $.ajax({
                           type: "POST",
                           url: url,
                           contentType: "application/json; charset=utf-8",
                           dataType: "json",
                           data: JSON.stringify(params),
      

      【讨论】:

        【解决方案6】:

        输入的意外结束意味着解析器过早结束。例如,它可能期待"abcd...wxyz",但只看到"abcd...wxy

        这可能是某处的错字错误,也可能是您在应用程序的不同部分混合编码时遇到的问题。

        一个例子:假设您正在使用 chrome.runtime.sendNativeMessage 从本机应用程序接收数据:

        chrome.runtime.sendNativeMessage('appname', {toJSON:()=>{return msg}}, (data)=>{
            console.log(data);
        });
        

        现在调用您的回调之前,浏览器将尝试使用JSON.parse 解析消息,如果supplied byte length 与数据不匹配,这可能会给您“输入意外结束”错误.

        【讨论】:

          【解决方案7】:

          我在 Node JS 中做了这个,它解决了这个问题:

          var data = JSON.parse(Buffer.concat(arr).toString());
          

          【讨论】:

            【解决方案8】:

            剧透:可能的服务器端问题

            这是我发现的,我的代码期望我的服务器的响应,当服务器只返回 200 个代码时,这还不够来自 json 解析器抛出错误 错误意外结束输入

            fetch(url, {
                    method: 'POST',
                    body: JSON.stringify(json),
                    headers: {
                      'Content-Type': 'application/json'
                    }
                  })
                    .then(res => res.json()) // here is my code waites the responce from the server
                    .then((res) => {
                      toastr.success('Created Type is sent successfully');
                    })
                    .catch(err => {
                      console.log('Type send failed', err);
                      toastr.warning('Type send failed');
                    })
            

            【讨论】:

              【解决方案9】:

              我在将包含 \n 的字符串解析为 JSON 时遇到了同样的错误。解决方案是使用string.replace('\n','\\n')

              【讨论】:

                【解决方案10】:

                在读取空的 JSON 文件时会发生此错误。

                为了避免在 NodeJS 中出现这个错误,我正在检查文件的大小:

                const { size } = fs.statSync(JSON_FILE);
                const content = size ? JSON.parse(fs.readFileSync(JSON_FILE)) : DEFAULT_VALUE;
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2016-06-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-09-30
                  • 1970-01-01
                  • 2023-03-15
                  相关资源
                  最近更新 更多