草庐IT

json - 解码 json http 响应

coder 2023-06-30 原文

我最近开始玩 GO,我正在尝试解码来自 http://www.oref.org.il/WarningMessages/alerts.json 的 JSON 响应。 .
出于某种原因,我无法理解解码失败,解码的结构是空的(我猜它与编码有某种关系)。

下面是代码,感谢任何帮助。

谢谢, 伊泰

package main

import (
  "fmt"
  "io/ioutil"
  "net/http"
  "encoding/json"
)

const alertsUrl = "http://www.oref.org.il/WarningMessages/alerts.json"

type Record struct {
  Id string `json:id`
  Title string `json:title`
  Data []string `json:data`
}

func main() {
  client := &http.Client{}
  req, err := http.NewRequest("GET", alertsUrl, nil)
  perror(err)

  req.Header.Add("Content-Type", "application/json; charset=utf-8")
  res, err := client.Do(req)
  perror(err)

  defer res.Body.Close()
  body, err := ioutil.ReadAll(res.Body)
  perror(err)

  var record Record
  json.Unmarshal(body, &record)
  fmt.Println(record)
}

func perror(err error) {
  if err != nil {
    panic(err)
  }
}

最佳答案

您忽略了 JSON Unmarshal 上的错误:

func Unmarshal(data []byte, v interface{}) error

看到它返回了一个错误。加上那个,

err = json.Unmarshal(body, &record)
perror(err)

看起来这是一个 Unicode 错误 — 您需要 decode the UTF-16 data .

你应该怎么做?看看this answer .基本上,一旦您像 body, err := ioutil.ReadAll(res.Body) 一样阅读正文,您就想将 UTF-16 字节解码为字符串。那里发生了很多事情,但我们可以采取一些自由:例如,在 Chrome 中拉出 URL,浏览器告诉我们它是 UTF-16 LE。所以我们可以跳过 ByteOrder 检测。所以这里的关键是这个函数:

func UTF16BytesToString(b []byte, o binary.ByteOrder) string {
    utf := make([]uint16, (len(b)+(2-1))/2)
    for i := 0; i+(2-1) < len(b); i += 2 {
        utf[i/2] = o.Uint16(b[i:])
    }
    if len(b)/2 < len(utf) {
        utf[len(utf)-1] = utf8.RuneError
    }
    return string(utf16.Decode(utf))
}

知道我们的字节顺序并将其传入,这会将原始字节数组转换为 UTF-16 字符的字符串。感谢用户 OneOfOne 的 comment ,我们还可以轻松检测 BOM。

结果:

package main

import (
    "encoding/binary"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "unicode/utf16"
    "unicode/utf8"
)

const alertsUrl = "http://www.oref.org.il/WarningMessages/alerts.json"

type Record struct {
    Id    string   `json:id`
    Title string   `json:title`
    Data  []string `json:data`
}

// LazyUTF16BytesToString converts UTF-16 encoded bytes, in big or little endian byte order,
// to a UTF-8 encoded string.
func LazyUTF16BytesToString(b []byte) string {
    if len(b)%2 != 0 {
        panic("len(b) % 2 != 0")
    }

    var codec binary.ByteOrder = binary.LittleEndian
    if b[0] == 0xFE && b[1] == 0xFF { //check and strip the BOM
        b = b[2:]
        codec = binary.BigEndian
    } else if b[0] == 0xFF && b[1] == 0xFE {
        b = b[2:]
    }

    utf := make([]uint16, (len(b)+(2-1))/2)
    for i := 0; i+(2-1) < len(b); i += 2 {
        utf[i/2] = codec.Uint16(b[i:])
    }
    if len(b)/2 < len(utf) {
        utf[len(utf)-1] = utf8.RuneError
    }
    return string(utf16.Decode(utf))
}

func main() {
    client := &http.Client{}
    req, err := http.NewRequest("GET", alertsUrl, nil)
    perror(err)

    req.Header.Add("Content-Type", "application/json; charset=utf-8")
    res, err := client.Do(req)
    perror(err)

    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    perror(err)

    bodyString := LazyUTF16BytesToString(body)

    var record Record
    err = json.Unmarshal([]byte(bodyString), &record)
    perror(err)
    fmt.Println(record)
}

func perror(err error) {
    if err != nil {
        panic(err)
    }
}

关于json - 解码 json http 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24681644/

有关json - 解码 json http 响应的更多相关文章

  1. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  2. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  3. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  4. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  5. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  6. ruby-on-rails - Rails 渲染带有驼峰命名法的 json 对象 - 2

    我在一个简单的RailsAPI中有以下Controller代码:classApi::V1::AccountsControllerehead:not_foundendendend问题在于,生成的json具有以下格式:{id:2,name:'Simpleaccount',cash_flows:[{id:1,amount:34.3,description:'simpledescription'},{id:2,amount:1.12,description:'otherdescription'}]}我需要我生成的json是camelCase('cashFlows'而不是'cash_flows'

  7. ruby - 使用 JSON gem 将自定义对象转换为 JSON - 2

    我正在学习如何使用JSONgem解析和生成JSON。我可以轻松地创建数据哈希并将其生成为JSON;但是,在获取一个类的实例(例如Person实例)并将其所有实例变量放入哈希中以转换为JSON时,我脑袋放屁。这是我遇到问题的例子:require"json"classPersondefinitialize(name,age,address)@name=name@age=age@address=addressenddefto_jsonendendp=Person.new('JohnDoe',46,"123ElmStreet")p.to_json我想创建一个.to_json方法,这样我就可以获

  8. ruby-on-rails - 如何使用驼峰键名称从 Rails 返回 JSON - 2

    我正在构建一个带有Rails后端的JS应用程序,为了不混淆snake和camelcases,我想通过从服务器返回camelcase键名来规范化这一切。因此,当从API返回时,user.last_name将返回user.lastName。我如何实现这一点?谢谢!编辑:添加Controller代码classApi::V1::UsersController 最佳答案 我的方法是使用ActiveModelSerializer和json_api适配器:在你的Gemfile中,添加:gem'active_model_serializers'创建

  9. ruby-on-rails - 如何将数组输出为 JSON? - 2

    我有以下内容:@array.inspect["x1","x2","adad"]我希望能够将其格式化为:client.send_message(s,m,{:id=>"x1",:id=>"x2",:id=>"adad"})client.send_message(s,m,???????)如何在????????中获得@array输出?空间作为ID?谢谢 最佳答案 {:id=>"x1",:id=>"x2",:id=>"adad"}不是有效的散列,因为您有键冲突它应该是这样的:{"ids":["x1","x2","x3"]}更新:@a=["x1

  10. ruby - 使用 jbuilder 创建具有动态哈希键的 JSON - 2

    这里我想输出带有动态组名的json而不是单词组@tickets.eachdo|group,v|json.group{json.array!vdo|ticket|json.partial!'tickets/ticket',ticket:ticketend}end@ticket是这样的散列{a:[....],b:[.....]}我想要这样的输出{a:[.....],b:[....]} 最佳答案 感谢@AntarrByrd,这个问题有类似的答案:JBuilderdynamickeysformodelattributes使用上面的逻辑我已经

随机推荐