WebClient 没有 return "valid" 字符串列表
WebClient does not return a "valid" list of Strings
我有一个 spring 启动应用程序,其中有一个端点,当点击时,returns 一个字符串列表。我还有另一个 spring 启动应用程序,它点击第一个应用程序的端点以获取数据。获取代码:
return webClient.get().uri("/sensors/get-cities").headers(httpHeaders -> {
httpHeaders.set("Authorization", auth);
}).retrieve()
.bodyToFlux(String.class).collectList().block();
上面生成了一个列表,但是当我在调试器中检查它时使用这种格式,"["city"]"
。外双引号,我得到它们,因为它是一个字符串,但括号和内双引号,我没有。我尝试替换这些字符,但我没有用括号(尝试过正则表达式)。就好像他们不在那里,但同时又在。我现在很困惑。但我认为获取代码的行为不正常,它应该产生一个有效的字符串数组。
您的 Springboot API returns 结果解析为 JSON(这是默认行为)。所以它首先构建一个字符串列表(在你的例子中只是一个字符串 "city"
然后将它序列化为 Json。在这种情况下,因为它是一个列表,所以它序列化为 JSON 数组与 JSON 对象相反。阅读 JSON here. So in your second Springboot app that hits the API from the first one should assume that you are getting JSON which you need to parse to get your list. To parse it you can use readValue() Json Jackson 库的 ObjectMapper
class 方法,这是默认的 JSON Springboot 中的库。您的代码将是
List<String> myList;
ObjectMapper = new ObjectMapper();
//Add setters for ObjectMapper configuration here if you want a specific config
try {
myList = objectMapper.readValue(myJsonString, List.class);
} catch(IOException ioe) {
...
}
此外,我还编写了自己的 Open-source 库,名为 MgntUtils,其中包括 JsonUtils
class,它是 Json Jackson 库的精简包装。它仅提供 Json 解析器和序列化器,但在许多情况下,这就是您所需要的。使用我的库,你只需要一个依赖项而不是 Jackson,并且 JsonUtils
class 只有 4 个方法,所以更容易理解。但在你的情况下,如果你使用我的库,代码将与上面的代码非常相似。它会是这样的:
List<String> myList;
try {
myList = JsonUtils.readObjectFromJsonString(myJsonString, List.class);
} catch(IOException ioe) {
...
}
请注意,在这种情况下,您不必实例化和配置 ObjectMapper
实例,因为 readObjectFromJsonString
是一个静态方法。无论如何,如果您有兴趣使用我的库,您可以找到 Maven 工件 here and The library itself with source code and javadoc is on Github here. Javadoc for JsonUtils
class is here
您可能得到的(我在这里猜测)是一个看起来像这样的响应主体:
[
"New York",
"Madrid",
"London"
]
然后您通过调用 bodyToFlux(String.class)
.
告诉 webflux 您想要将正文转换为 String
的 Flux
因此框架获取整个响应并从中生成一个字符串
// A string of the entire array (im escaping the quotation marks)
"[\"New York\",\"Madrid\",\"London\"]"
然后框架会把整个东西扔到Flux
中,这意味着它在Flux
中占据第一个位置。然后,您通过调用 collectList
将所有值发送到 List
等效代码是:
List<String> oneString = Flux.just("[\"New York\",\"Madrid\",\"London\"]")
.collectList()
.block();
所以你得到一个列表,里面有一个字符串,就是整个正文。
你可能想要做的是得到一个列表。这是一种方法:
List<String> strings = webClient.get()
.uri("/sensors/get-cities")
.headers(httpHeaders -> {
httpHeaders.set("Authorization", auth);
})
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<String>>() {})
.block();
Spring 说明 ParameterizedTypeReference
:
The purpose of this class is to enable capturing and passing a generic Type. In order to capture the generic type and retain it at runtime
所以它有点像 class 确保我们可以使用像 List<T>
这样的通用类型并帮助我们获得类型信息。
所以我们现在要做的是获取响应并直接告诉框架正文是一个字符串列表。我们不需要再执行 collectList
,因为框架会为我们将其粘贴到列表中。然后我们调用 block
等待响应。
我有一个 spring 启动应用程序,其中有一个端点,当点击时,returns 一个字符串列表。我还有另一个 spring 启动应用程序,它点击第一个应用程序的端点以获取数据。获取代码:
return webClient.get().uri("/sensors/get-cities").headers(httpHeaders -> {
httpHeaders.set("Authorization", auth);
}).retrieve()
.bodyToFlux(String.class).collectList().block();
上面生成了一个列表,但是当我在调试器中检查它时使用这种格式,"["city"]"
。外双引号,我得到它们,因为它是一个字符串,但括号和内双引号,我没有。我尝试替换这些字符,但我没有用括号(尝试过正则表达式)。就好像他们不在那里,但同时又在。我现在很困惑。但我认为获取代码的行为不正常,它应该产生一个有效的字符串数组。
您的 Springboot API returns 结果解析为 JSON(这是默认行为)。所以它首先构建一个字符串列表(在你的例子中只是一个字符串 "city"
然后将它序列化为 Json。在这种情况下,因为它是一个列表,所以它序列化为 JSON 数组与 JSON 对象相反。阅读 JSON here. So in your second Springboot app that hits the API from the first one should assume that you are getting JSON which you need to parse to get your list. To parse it you can use readValue() Json Jackson 库的 ObjectMapper
class 方法,这是默认的 JSON Springboot 中的库。您的代码将是
List<String> myList;
ObjectMapper = new ObjectMapper();
//Add setters for ObjectMapper configuration here if you want a specific config
try {
myList = objectMapper.readValue(myJsonString, List.class);
} catch(IOException ioe) {
...
}
此外,我还编写了自己的 Open-source 库,名为 MgntUtils,其中包括 JsonUtils
class,它是 Json Jackson 库的精简包装。它仅提供 Json 解析器和序列化器,但在许多情况下,这就是您所需要的。使用我的库,你只需要一个依赖项而不是 Jackson,并且 JsonUtils
class 只有 4 个方法,所以更容易理解。但在你的情况下,如果你使用我的库,代码将与上面的代码非常相似。它会是这样的:
List<String> myList;
try {
myList = JsonUtils.readObjectFromJsonString(myJsonString, List.class);
} catch(IOException ioe) {
...
}
请注意,在这种情况下,您不必实例化和配置 ObjectMapper
实例,因为 readObjectFromJsonString
是一个静态方法。无论如何,如果您有兴趣使用我的库,您可以找到 Maven 工件 here and The library itself with source code and javadoc is on Github here. Javadoc for JsonUtils
class is here
您可能得到的(我在这里猜测)是一个看起来像这样的响应主体:
[
"New York",
"Madrid",
"London"
]
然后您通过调用 bodyToFlux(String.class)
.
String
的 Flux
因此框架获取整个响应并从中生成一个字符串
// A string of the entire array (im escaping the quotation marks)
"[\"New York\",\"Madrid\",\"London\"]"
然后框架会把整个东西扔到Flux
中,这意味着它在Flux
中占据第一个位置。然后,您通过调用 collectList
将所有值发送到 List
等效代码是:
List<String> oneString = Flux.just("[\"New York\",\"Madrid\",\"London\"]")
.collectList()
.block();
所以你得到一个列表,里面有一个字符串,就是整个正文。
你可能想要做的是得到一个列表。这是一种方法:
List<String> strings = webClient.get()
.uri("/sensors/get-cities")
.headers(httpHeaders -> {
httpHeaders.set("Authorization", auth);
})
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<String>>() {})
.block();
Spring 说明 ParameterizedTypeReference
:
The purpose of this class is to enable capturing and passing a generic Type. In order to capture the generic type and retain it at runtime
所以它有点像 class 确保我们可以使用像 List<T>
这样的通用类型并帮助我们获得类型信息。
所以我们现在要做的是获取响应并直接告诉框架正文是一个字符串列表。我们不需要再执行 collectList
,因为框架会为我们将其粘贴到列表中。然后我们调用 block
等待响应。