使用 Jackson 属性累积状态作为序列化的副产品

Using a Jackson attribute to accumulate state as a byproduct of serialization

这是我的场景:

所需的数据结构:

path type
household.primaryEmail email-address
household.members[0].cellNumber phone-number
household.members[0].firstName first-name
household.members[1].cellNumber phone-number

我不关心使用的具体 pathing/location 语言(JSON 指针,Json 路径)。

我可以通过反思和维护我自己的路径来实现这一点,但感觉就像我应该能够用 Jackson 做的事情,因为它已经在进行遍历了。我很确定使用 Jackson 的属性功能是附加我将累积数据结构的对象的正确方法。但是,我想不出一种在运行时获取路径的方法。这是我当前的 Scala 尝试(hackily?)建立在一个过滤器之上,该过滤器通过一个 mixin 应用于所有对象:

object Test {
@JsonFilter("pii")
class PiiMixin {
}

class PiiAccumulator {
  val state =  mutable.ArrayBuffer[String]()

  def accumulate(test: String): Unit = state += test
}

def main(args: Array[String]): Unit = {

  val filter = new SimpleBeanPropertyFilter() {

    override def serializeAsField(pojo: Any, jgen: JsonGenerator, provider: SerializerProvider, writer: PropertyWriter): Unit = {

      if (writer.getAnnotation(classOf[PiiData]) != null) {
        provider.getAttribute("pii-accumulator").asInstanceOf[PiiAccumulator].accumulate(writer.getFullName.toString)
      }

      super.serializeAsField(pojo, jgen, provider, writer)
    }

    override def include(writer: BeanPropertyWriter): Boolean = true
    override def include(writer: PropertyWriter): Boolean = true
  }

  val provider = new SimpleFilterProvider().addFilter("pii", filter)

  val mapper = new ObjectMapper()

  mapper.addMixIn(classOf[Object], classOf[PiiMixin])

  val accum = new PiiAccumulator()
  
  mapper.writer(provider)
    .withAttributes("pii-accumulator", accum)
    .writeValueAsString(null) // Pass in any arbitrary object here
}
}

此代码使我能够动态缓冲包含 PII 的 属性 名称列表,但我不知道如何在生成的 JSON 文档中获取它们的位置。也许 Jackson 架构以某种方式阻止了在运行时知道这一点。有没有其他地方我可以挂钩做这样的事情,也许在转换为 JsonNode 时?

谢谢!

好的,找到了。您可以在序列化期间通过 JsonGenerator.getOutputContext.pathAsPointer() 访问递归 path/location。因此,将我上面的代码更改为以下内容:

        if (writer.getAnnotation(classOf[PIIData]) != null) { 
          provider.getAttribute("pii").asInstanceOf[PiiAccumulator]
          .accumulate(jgen.getOutputContext.pathAsPointer().toString + "/" + writer.getName)
        }

我能够动态缓冲生成的 JSON 文档中的特殊位置列表,以进行进一步的动态处理。