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

如何结合Circe Optics与解码功能提取并解析JSON中的Person对象?

问题分析与解决:Circe Optics提取JSON对象并解码为样例类

咱们先拆解下你遇到的问题,再一步步解决:

为什么你的方法无法生效?

你写的root.response.person.string这个Circe Optics路径,本质是在JSON里寻找类型为字符串的节点,但你的person是一个嵌套的JSON对象({"firstname": "foo", "lastname":"bar"}),并不是字符串类型。

这就导致p.getOption(json)会返回None,之后你调用.get直接获取Option的值,不仅会抛出NoSuchElementException,更别说后续的解码操作了——因为根本拿不到有效的字符串输入。

两种可行的解决办法

办法一:直接用Optics解码为样例类(推荐,更高效)

不需要先转成字符串,直接通过Optics把JSON对象解码成Person样例类,步骤如下:

  1. 首先为Person生成Circe的解码器(用半自动推导最方便):
import io.circe.Decoder
import io.circe.generic.semiauto._

case class Person(firstname: String, lastname: String)
implicit val personDecoder: Decoder[Person] = deriveDecoder[Person]
  1. 使用as[Person]来定义针对Person类型的Optics路径,然后安全提取:
import io.circe.parser._
import io.circe.optics._
import io.circe.optics.JsonPath._

val json = parse("""{"response": {"person": {"firstname": "foo", "lastname":"bar"}}}""").right.get

// 定义能解码Person的路径
val personPath = root.response.person.as[Person]
// 安全获取Option[Person],避免空指针
val personOpt = personPath.getOption(json)

// 处理结果的示例
personOpt match {
  case Some(person) => println(s"成功提取Person: $person")
  case None => println("未找到有效的Person节点")
}

办法二:先获取Person对象的JSON字符串再解码

如果确实需要先拿到person对象的字符串形式,那得先提取Json类型的节点,再转成字符串:

import io.circe.parser._
import io.circe.optics._
import io.circe.optics.JsonPath._
import io.circe.Decoder
import io.circe.generic.semiauto._

case class Person(firstname: String, lastname: String)
implicit val personDecoder: Decoder[Person] = deriveDecoder[Person]

val json = parse("""{"response": {"person": {"firstname": "foo", "lastname":"bar"}}}""").right.get

// 先提取Person对应的Json节点
val personJsonOpt = root.response.person.getOption(json)
// 转成紧凑的JSON字符串(用spaces2可以得到格式化的字符串)
val personStrOpt = personJsonOpt.map(_.noSpaces)

// 解码并处理结果
personStrOpt.foreach { str =>
  decode[Person](str) match {
    case Right(person) => println(s"解码成功: $person")
    case Left(err) => println(s"解码失败: ${err.getMessage}")
  }
}

额外注意点

永远不要直接用.get来获取Option的值——这会在值不存在时抛出异常。建议用模式匹配、foreach、getOrElse或者for-comprehension来安全处理Option和Either类型。

内容的提问来源于stack exchange,提问作者Knows Not Much

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:39:01