【问题标题】:Getting error when receiving JSON after post method in swift在 swift 中的 post 方法后接收 JSON 时出错
【发布时间】:2018-05-06 23:30:12
【问题描述】:

我正在向我的后端发送一个 POST 请求,但是我收到了这个错误:

The given data was not valid JSON.",
underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840
"JSON text did not start with array or object and option to allow
 fragments not set."
UserInfo={NSDebugDescription=JSON text did not start with array
or object and option to allow fragments not set.})))

这是我用来发送/获取数据的代码:

func fetchDataWithParameters(){

    struct Response: Codable {
        let status: String?
        let error: String?
    }

    let decoder = JSONDecoder()
    HTTP.POST("somelinkhere", parameters: ["date": self.weekDays[self.itemSelectedIndex]]) { response in
        if let error = response.error {
            print("got an error: \(error)")
            return
        }
        do {
            let resp = try decoder.decode(Response.self, from: response.data)
            if let err = resp.error {
                print("got an error: \(err)")
            }
            if let status = resp.status {
                print("completed: \(status)")

            }
        } catch let error {
            print("decode json error: \(error)")
        }
    }
}

使用我的终端我正在尝试执行手动 POST 请求,我得到了这个:

Admins-MacBook-Pro:hello-world admin$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" somelinkhere
HTTP/1.1 200 OK
Server: openresty/1.9.15.1
Date: Thu, 03 May 2018 23:42:04 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 39
Connection: keep-alive
X-Clacks-Overhead: GNU Terry Pratchett

"{\"name\": \"Timo\", \"age\": \"39\"}"

这让我想知道唯一可能的错误可能是我如何解码 JSON。为什么它还能与终端一起使用?有什么想法吗?

正如@patru 建议的那样,我在此处包含打印:

catch let error {
    print(String(data:response.data, encoding: .utf8)!)
    print("decode json error: \(error)")
}

结果如下:

"{\"name\": \"Mergim\", \"age\": \"39\"}"
decode json error: dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})))

似乎我像使用 curl 一样获取 JSON,但由于某种原因 swift 不认为它是有效的 JSON?这就是我的 post 方法在后端的样子:

@app.route('/', methods=['GET', 'POST'])
def index():

    jsonData = {"name": "Timo", "age": "39"}
    jsonData1 = {"name": "Mergim", "age": "39"}

    if request.method=='GET':
        return json.dumps(jsonData)

    elif request.method=='POST':
        return json.dumps(jsonData1)

编辑

    jsonData = '{"name": "Timo", "age": "39"}'
    jsonData1 = '{"name": "Mergim", "age": "39"}'

改为:

    jsonData = {"name": "Timo", "age": "39"}
    jsonData1 = {"name": "Mergim", "age": "39"}

【问题讨论】:

  • 鉴于您的curl 输出,这应该是有效的 JSON,因为您的错误消息似乎不是。如果不看你实际得到什么,很难说。请尝试打印print(String(data:response.data, encoding: .utf8)) 并向我们提供输出,这可能会有所帮助。 (请通过编辑您的问题来做到这一点,因为您可以看到代码在(更有限的)cmets 中看起来很混乱。)
  • 您在curl 命令中的哪个位置传递了您在代码中传递的“日期”参数?
  • @MikeTaverne 在这种情况下没关系。我只是简单地使用任何值来获得响应。实施日期将在稍后公布。

标签: swift post jsondecoder


【解决方案1】:

这很微妙,但不管你信不信,问题出在服务器上!

实际上你的代码看起来......有点不对劲,但还不错,所以我运行了这个 Playground:

import Cocoa

let jsonData = "{\"name\": \"Mergim\", \"age\": \"39\"}".data(using: .utf8)!

struct Response: Codable {
    let status: String?
    let error: String?
}

struct NameAge: Codable {
    let name: String
    let age: String
}

do {
    let resp = try JSONDecoder().decode(Response.self, from: jsonData)
    print(resp)
    let na = try JSONDecoder().decode(NameAge.self, from: jsonData)
    print(na)
} catch {
    print(error)
}

print(String(data:jsonData, encoding: .utf8)!)

由于您的 Response 结构与您的数据结构不完全匹配,我实现了 NameAge 以便获得更合适的东西。尽管Response 的值仍然值得怀疑,但两者仍然会解析。我也很困惑,直到我查看了您的错误消息:它抱怨您数据中的第一个字符!我终于在 Playground 中添加了最后一行,问题就清楚了。

您为您的服务器(我猜它是 ruby​​ 或类似的东西)提供了一个有效的 String 对象,它把它变成了相应的 JSON,它仍然代表 JSON 中的 只是一个字符串 .这解释了您拥有的双引号,而我的 Playground 没有产生。您可能应该将您的jsonData 提供为Hash,服务器将正确转换它(不带双引号)。出于随机原因 JSONDecoder 不想解码简单的 JSON 字符串,但这是我的借口。

顺便说一句:您可能希望将age 的类型更改为Int,一旦您可以正确传递它。

【讨论】:

  • 考虑到你所说的,我只是改变了我在服务器中创建字符串的方式。检查我对服务器代码所做的编辑。我现在没有收到任何错误,但是为什么它不会打印出“已完成”,我设法打印了响应并且它是正确的,但是我希望能够在它到达请求的完成部分时做一些事情,即 if let status = resp .status ??
  • 我以为我已经在我的代码中明确说明了这一点:您将无法从 包含 @987654333 的一段 JSON 中解码 statuserror @ 和 age。只要您将它们定义为可选项,您的decode 仍然可以使用,但您的status 将始终为空。您应该能够从 response 对象中获得一些 HTTP 状态,这些对象由 HTTP.POST 方法提供。运行我的 Playground,你会发现只有如果你 decode NameAgenot Response,你可以从给定的字符串中得到合理的值。
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2017-09-08
  • 2018-10-19
  • 2022-06-25
  • 2016-06-12
  • 1970-01-01
相关资源
最近更新 更多