Post json of unknown class with Feign client
Post json of unknown class with Feign client
我的服务必须将 json 数据重定向到另一个服务。在我在 feign client 上看到的所有例子中,sender 知道发送对象的数据类型,所以它看起来像这样:
@RequestMapping("some/path", consumes = [MediaType.APPLICATION_JSON_VALUE])
interface UploadClient {
@PostMapping("upload")
fun upload(book: Book): Long
}
我的问题是我没有书class,我只好转发json。我试过用字符串来做,像这样:
客户端界面:
@RequestMapping("some/path")
interface UploadClient {
@PostMapping("/upload", consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE))
fun import(@RequestBody strangeData: String): Long
}
假工厂:
class DefaultFeignClientFactory() : FeignClientFactory {
override fun <T> getClient(target: Class<T>, url: String): T {
return registry.getOrPut(target) {
Feign.builder()
.target(target, url)
} as T
}
}
使用 OSGi 实例化客户端:
<bean id="uploadClient" factory-ref="feignClientFactory" factory-method="getClient">
<argument value="com.blah.blahblah.UploadClient"/>
</bean>
与接收方相同的接口是:
@RequestMapping("some/path")
interface Loader {
@PostMapping("/upload")
fun import(@RequestBody myBooks: Collection<Book>): Long
}
如果我直接在接收器中抛出 json (curl/postman/etc),它会反序列化它并且工作正常。
将字符串传递给假装客户端是可行的,但不幸的是,接收方无法以这种方式反序列化它。
所以我尝试将其更改为 byte[](Kotlin 中的 ByteArray):
@PostMapping("/upload", consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE))
fun import(@RequestBody strangeData: ByteArray): Long
它属于 org.springframework.web.HttpMediaTypeNotSupportedException message: Unsupported Media Type
MediaType.APPLICATION_OCTET_STREAM_VALUE
和 MediaType.ALL_VALUE
同样幸运(实际上 ALL_VALUE 因其他一些错误而失败)- 数据不会以任何形式发送到接收方服务。
在这些情况下我必须选择什么 Java 数据类型和什么 MediaType?
提前致谢。
声明您的方法接受泛型 JSON 的一种方法是使用 Jackson 的 JsonNode 作为您的参数类型。
@RequestMapping(value = ["some/path"], consumes = [MediaType.APPLICATION_JSON_VALUE])
interface UploadClient {
@PostMapping("upload")
fun upload(@RequestBody book: JsonNode): Long
}
这样,您就可以 post JSON 对象、JSON 数组、字符串、数字或具有任意嵌套的布尔值。这是一个例子:
val book: ObjectNode = JsonNodeFactory.instance.objectNode()
.put("authors", JsonNodeFactory.instance.arrayNode()
.add("John Doe")
.add("Jane Doe"))
.put("title", "First Book about the Does")
.put("year", 2018)
val id = uploadClient.upload(book)
这相当于下面的请求
POST /some/path HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"authors": ["John Doe", "Jane Doe"],
"title": "First Book about the Does",
"year": 2018
}
在服务器端也可以使用 JsonNode。
我的服务必须将 json 数据重定向到另一个服务。在我在 feign client 上看到的所有例子中,sender 知道发送对象的数据类型,所以它看起来像这样:
@RequestMapping("some/path", consumes = [MediaType.APPLICATION_JSON_VALUE])
interface UploadClient {
@PostMapping("upload")
fun upload(book: Book): Long
}
我的问题是我没有书class,我只好转发json。我试过用字符串来做,像这样:
客户端界面:
@RequestMapping("some/path")
interface UploadClient {
@PostMapping("/upload", consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE))
fun import(@RequestBody strangeData: String): Long
}
假工厂:
class DefaultFeignClientFactory() : FeignClientFactory {
override fun <T> getClient(target: Class<T>, url: String): T {
return registry.getOrPut(target) {
Feign.builder()
.target(target, url)
} as T
}
}
使用 OSGi 实例化客户端:
<bean id="uploadClient" factory-ref="feignClientFactory" factory-method="getClient">
<argument value="com.blah.blahblah.UploadClient"/>
</bean>
与接收方相同的接口是:
@RequestMapping("some/path")
interface Loader {
@PostMapping("/upload")
fun import(@RequestBody myBooks: Collection<Book>): Long
}
如果我直接在接收器中抛出 json (curl/postman/etc),它会反序列化它并且工作正常。 将字符串传递给假装客户端是可行的,但不幸的是,接收方无法以这种方式反序列化它。 所以我尝试将其更改为 byte[](Kotlin 中的 ByteArray):
@PostMapping("/upload", consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE))
fun import(@RequestBody strangeData: ByteArray): Long
它属于 org.springframework.web.HttpMediaTypeNotSupportedException message: Unsupported Media Type
MediaType.APPLICATION_OCTET_STREAM_VALUE
和 MediaType.ALL_VALUE
同样幸运(实际上 ALL_VALUE 因其他一些错误而失败)- 数据不会以任何形式发送到接收方服务。
在这些情况下我必须选择什么 Java 数据类型和什么 MediaType? 提前致谢。
声明您的方法接受泛型 JSON 的一种方法是使用 Jackson 的 JsonNode 作为您的参数类型。
@RequestMapping(value = ["some/path"], consumes = [MediaType.APPLICATION_JSON_VALUE])
interface UploadClient {
@PostMapping("upload")
fun upload(@RequestBody book: JsonNode): Long
}
这样,您就可以 post JSON 对象、JSON 数组、字符串、数字或具有任意嵌套的布尔值。这是一个例子:
val book: ObjectNode = JsonNodeFactory.instance.objectNode()
.put("authors", JsonNodeFactory.instance.arrayNode()
.add("John Doe")
.add("Jane Doe"))
.put("title", "First Book about the Does")
.put("year", 2018)
val id = uploadClient.upload(book)
这相当于下面的请求
POST /some/path HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"authors": ["John Doe", "Jane Doe"],
"title": "First Book about the Does",
"year": 2018
}
在服务器端也可以使用 JsonNode。