Open philippeu opened 2 years ago
Hello @philippeu, thanks for reporting this. I was able to reproduce the issue. Will work on it.
@philippeu Have looked into this further. Actually, the data that comes from the sort json of this kind: { "empty": true, "sorted": false, "unsorted": true }
is not enough to construct a viable Sort
object. If you do not set feign.autoconfiguration.jackson.enabled: true
, you will simply get an exception, cause it cannot be deserialised. That's probably why @cbezmen has opted for returning null
in such a scenario. Could you provide some more details regarding your usecase?
Hi Olga,
I have a service returning Pageable.
by default MappingJackson2HttpMessageConverter
, serialize Sort
object to (using PageImpl
)
"sort": { "empty": true, "sorted": false, "unsorted": true }
This service is calling another one via a feign client which is also returning a Pageable
feign.autoconfiguration.jackson.enabled
must be set to true
in order for the feign client to deserialize the pagination.
once feign jackson is enabled, it registered the SortJacksonModule
deserializer and it can read the paginated response.
this is good
the SortJacksonModule
serializer is also registered in ObjectMapper
of MappingJackson2HttpMessageConverter
and then used to serialize the Sort
object to
"sort": []
so services having feign jackson enabled do not provide the same response format (sort is serialized as an array) than the ones having feign jackson disabled (sort is serialized as an object).
I work around that by providing a CustomSortJacksonModule
serializer and CustomSortJsonComponent
.
@philippeu Could you please provide the code of CustomSortJacksonModule
serializer and CustomSortJsonComponent
? It will be easier for us to understand your use-case then.
Here they are:
public class CustomSortJacksonModule extends SortJacksonModule {
@Override
public String getModuleName() {
return "SortModule";
}
@Override
public Version version() {
return new Version(0, 1, 0, "", null, null);
}
@Override
public void setupModule(SetupContext context) {
var serializers = new SimpleSerializers();
serializers.addSerializer(Sort.class, new CustomSortJsonComponent.SortSerializer());
context.addSerializers(serializers);
var deserializers = new SimpleDeserializers();
deserializers.addDeserializer(Sort.class, new CustomSortJsonComponent.SortDeserializer());
context.addDeserializers(deserializers);
}
}
public class CustomSortJsonComponent {
public static class SortSerializer extends JsonSerializer<Sort> {
private record CustomSort(boolean empty, boolean sorted, boolean unsorted) {};
@Override
public void serialize(Sort value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeObject(new CustomSort(value.isEmpty(), value.isSorted(), value.isUnsorted()));
}
@Override
public Class<Sort> handledType() {
return Sort.class;
}
}
public static class SortDeserializer extends JsonDeserializer<Sort> {
@Override
public Sort deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
var treeNode = jsonParser.getCodec().readTree(jsonParser);
if (treeNode.isArray()) {
var arrayNode = (ArrayNode) treeNode;
var orders = new ArrayList<Sort.Order>();
arrayNode.forEach(jsonNode -> orders.add(new Sort.Order(Sort.Direction.valueOf(jsonNode.get("direction").textValue()), jsonNode.get("property").textValue())));
return Sort.by(orders);
}
return null;
}
@Override
public Class<Sort> handledType() {
return Sort.class;
}
}
}
a better solution would be to have an specific object mapper for feign not interfering with spring one maybe.
@philippeu - thanks for providing the samples. I thought you meant deserialising, cause when a Sort
body is passed on, unless you provide an Encoder
bean different from PageableSpringEncoder
, it will not be serialised, but passed as request params instead. The current serialisation provides the bits necessary to do the sorting. Since you have a viable workaround, we're going to wait with this to see if there's any more interest in it within the community.
ok, thanks Olga!
Hi @philippeu @OlgaMaciaszek I am facing this same issue.
Is there any other development here -
a better solution would be to have an specific object mapper for feign not interfering with spring one maybe.
spring serializes
Sort
as an object"sort": { "empty": true, "sorted": false, "unsorted": true }
when
SortJacksonModule
is enabled (feign.autoconfiguration.jackson.enabled: true
)Sort
is serialize as an array bySortJsonComponent.SortSerializer
."sort": []
since
SortJacksonModule
is in the spring context the controller response includes the Sort array creating inconsistency between the controller response with and withoutSortJacksonModule