如何从双重嵌套响应中解析JSON

时间:2019-05-09 06:32:33

标签: json crystal-lang

如果我收到cars端点的JSON响应:

{
  data: {
    cars: [
      { make: "Tesla", model: "S" }
    ]
  }
}

我有一个Car班:

class Car
  JSON.mapping(
    make: String,
    model: String
  )
end

如何解析响应,以使根下降两级?我知道我可以做Car.from_json(json_string, "data"),但找不到指定另一个根密钥的方法。

如果没有办法做到这一点,而又不为cars级别创建另一个类,最简单的方法是什么?

1 个答案:

答案 0 :(得分:3)

您可以在这里采用几种方法。

一种简单的方法(尽管效率最低)只是解析两次:

cars = Array(Car).from_json(JSON.parse(json)["data"]["cars"].to_json)

https://carc.in/#/r/6vnk

然后,正如您提到的,您可以为外部类创建映射。与您所拥有的相比,没有真正更快的方法:

class Root
  JSON.mapping(data: Data)
end

class Data
  JSON.mapping(cars: Array(Car))
end

class Car
  JSON.mapping(
    make: String,
    model: String
  )
end

cars = Root.from_json(json).data.cars

https://carc.in/#/r/6vnm

或者,如果您更喜欢使用JSON::Serializable API:

class Root
  include JSON::Serializable
  property data : Data
end

class Data
  include JSON::Serializable
  property cars : Array(Car)
end

class Car
  include JSON::Serializable
  property  make : String
  property  model : String
end

cars = Root.from_json(json).data.cars

https://carc.in/#/r/6vno

最后,最后一种方法是直接驱动JSON::PullParser API:

parser = JSON::PullParser.new(json)
cars = nil
parser.on_key("data") do
  parser.on_key("cars") do
    cars = Array(Car).new(parser)
  end
end

https://carc.in/#/r/6vni