在 Crystal 应用程序中使用 JSON::Serialized 反序列化 PascalCased 属性时出现 JSON::SerializedError

问题描述 投票:0回答:1

我正在开发一个 Crystal 应用程序并使用一个 API,该 API 的某些端点属性不一致地使用 PascalCase,而不是 CamelCase。不幸的是,这会导致

JSON::Serializable
出现问题,它不能顺利处理 PascalCase 属性。我已经能够使用 .from_json 成功反序列化来自其他 API 端点的响应,只要属性遵循驼峰命名约定即可。

解析响应:

  api_url = "api.notmyapi.com"
  client = HTTP::Client.new(api_url)
  params = "/api?lets-get-some-pascal-case-i-guess"
  
  json_response = PascalCaseResponse.from_json(client.get(params).body)

  puts "json_response = #{json_response}" # No Bueno.

这在具有正确驼峰命名约定的所有其他端点上都可以正常工作。

但是,这是我的 Response 类的样子,它是直接根据 API 返回的 JSON 结构建模的...

class PascalCaseResponse
  include JSON::Serializable

  property PropertyOne : String
  property SomeOtherProperty : String

  ....

  property WhereAreTheCamels : String
end

...按照 API 端点响应的结构建模:

  {
     "PropertyOne":"I am a String",
     "SomeOtherProperty":"So am I!",

     ....

     "WhereAreTheCamels":"I do not know"
  }

这会产生此异常:

/Users/tyler/Code/project  $ crystal build src/main.cr; ./main
In src/responses/someresponse.cr:37:23

 37 | property PropertyOne : String
                           ^
Error: unexpected token: ":"
Unhandled exception: Missing JSON attribute: PropertyOne

让我相信这是 PascalCase 的是,当我将其属性更改为

propertyOne
时,它会继续抱怨
SomeOtherProperty
,但也抱怨
PropertyOne
,我觉得这很奇怪。

/Users/tyler/Code/project  $ crystal build src/main.cr; ./main
In src/responses/someresponse.cr:38:16

 38 | property SomeOtherProperty : String
                   ^
Error: unexpected token: ":"
Unhandled exception: Missing JSON attribute: PropertyOne

如何告诉

JSON::Serializable
将 PascalCase JSON 属性映射到我显然想保留驼峰式命名的 Response 对象?

我已经尝试过了

@[JSON::Field(key: "PascalCase")]
property camelCase: String

但这不起作用,并且来自 Kotlin/Java 序列化背景,这似乎是可行的方法。

我错过了什么吗?

json deserialization json-deserialization crystal-lang
1个回答
0
投票

PropertyOne
不是有效的方法名称,因此会出现错误。您可以像您尝试过的那样使用
propertyOne
,但按照惯例,Crystal 方法名称是蛇形的。您使用
JSON::Field
的做法是正确的,但您必须对 every 属性执行此操作。比如:

class PascalCaseResponse
  include JSON::Serializable

  @[JSON::Field(key: "PropertyOne")]
  property property_one : String

  @[JSON::Field(key: "SomeOtherProperty")]
  property some_other_property : String

  @[JSON::Field(key: "WhereAreTheCamels")]
  property where_are_the_camels : String
end

应该可以解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.