You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中使用JSON.parse转换Routeguide::Rectangle对象报错问题

Ruby JSON解析嵌套自定义类报错解决

问题背景

我有一个Ruby自定义类Routeguide::Rectangle,结构如下(其中lo和hi都是Routeguide::Point类的实例):

<Routeguide::Rectangle: lo: <Routeguide::Point: latitude: 400000000, longitude: -750000000>, hi: <Routeguide::Point: latitude: 420000000, longitude: -730000000>>

对应的正确JSON字符串为:

json_string = '{"lo":{"latitude":400000000,"longitude":-750000000},"hi":{"latitude":420000000,"longitude":-730000000}}'

尝试用以下代码将JSON解析为Routeguide::Rectangle对象:

JSON.parse(json_string, object_class: Routeguide::Rectangle)

执行后抛出错误:

#<ArgumentError: Unknown field: latitude>

堆栈信息:

[
  "/Users/psen/.rbenv/versions/2.7.7/lib/ruby/2.7.0/json/common.rb:156:in `[]='",
  "/Users/psen/.rbenv/versions/2.7.7/lib/ruby/2.7.0/json/common.rb:156:in `parse'",
  "/Users/psen/.rbenv/versions/2.7.7/lib/ruby/2.7.0/json/common.rb:156:in `parse'"
]

报错原因

Ruby标准库的JSON.parse方法使用object_class参数时,只会将顶层哈希转换为指定类的实例,但不会自动处理嵌套的自定义类。当解析到lo或hi内部的latitude字段时,会尝试直接给Routeguide::Rectangle实例设置这个不存在的属性,导致报错。

解决方案

方案1:手动解析构建对象

先把JSON解析成普通哈希,再逐层创建自定义类实例:

hash = JSON.parse(json_string)
lo_point = Routeguide::Point.new(latitude: hash["lo"]["latitude"], longitude: hash["lo"]["longitude"])
hi_point = Routeguide::Point.new(latitude: hash["hi"]["latitude"], longitude: hash["hi"]["longitude"])
rectangle = Routeguide::Rectangle.new(lo: lo_point, hi: hi_point)

方案2:给自定义类添加from_json方法

在Routeguide::Point和Routeguide::Rectangle中实现专属的JSON解析逻辑,封装细节:

class Routeguide::Point
  attr_accessor :latitude, :longitude

  def initialize(latitude:, longitude:)
    @latitude = latitude
    @longitude = longitude
  end

  def self.from_json(json_str)
    hash = JSON.parse(json_str)
    new(latitude: hash["latitude"], longitude: hash["longitude"])
  end
end

class Routeguide::Rectangle
  attr_accessor :lo, :hi

  def initialize(lo:, hi:)
    @lo = lo
    @hi = hi
  end

  def self.from_json(json_str)
    hash = JSON.parse(json_str)
    lo_point = Routeguide::Point.from_json(JSON.generate(hash["lo"]))
    hi_point = Routeguide::Point.from_json(JSON.generate(hash["hi"]))
    new(lo: lo_point, hi: hi_point)
  end
end

# 使用方式
rectangle = Routeguide::Rectangle.from_json(json_string)

方案3:重写[]=方法适配嵌套解析

通过重写Routeguide::Rectangle的[]=方法,识别嵌套字段并转换为对应类实例:

class Routeguide::Rectangle
  attr_accessor :lo, :hi

  def []=(key, value)
    if %w[lo hi].include?(key)
      # 将嵌套哈希转换为Routeguide::Point实例
      instance_variable_set("@#{key}", Routeguide::Point.new(latitude: value["latitude"], longitude: value["longitude"]))
    else
      super
    end
  end
end

# 现在可以直接用JSON.parse解析
rectangle = JSON.parse(json_string, object_class: Routeguide::Rectangle)

内容的提问来源于stack exchange,提问作者Prateek Sen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 07:50:32