Add Gson converter immediately before default Jackson converter
Previously, when the preferred json mapper was set to Gson, the Gson HTTP message converter was added before any other converters. This changed the form of String responses that were already valid. When Jackson is in use, a string converter is used as it appears earlier in the list than the Jackson converter. When the mapper is switched to Gson, the Gson converter is added first in the list of converters and the Strong converter is no longer used. This results in the String, that was already valid JSON, being converted again. This changes its form as quotes are escaped, etc. This commit updates HttpMessageConverters so that the Gson converter is added to the list immediately before the default Jackson converter. This is done by considering the Gson converter to be an equivalent of the Jackson converter. Fixes gh-27354
This commit is contained in:
parent
2f54198e31
commit
fe081b1742
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,8 +20,10 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||
|
@ -63,6 +65,15 @@ public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>>
|
|||
NON_REPLACING_CONVERTERS = Collections.unmodifiableList(nonReplacingConverters);
|
||||
}
|
||||
|
||||
private static final Map<Class<?>, Class<?>> EQUIVALENT_CONVERTERS;
|
||||
|
||||
static {
|
||||
Map<Class<?>, Class<?>> equivalentConverters = new HashMap<>();
|
||||
putIfExists(equivalentConverters, "org.springframework.http.converter.json.MappingJackson2HttpMessageConverter",
|
||||
"org.springframework.http.converter.json.GsonHttpMessageConverter");
|
||||
EQUIVALENT_CONVERTERS = Collections.unmodifiableMap(equivalentConverters);
|
||||
}
|
||||
|
||||
private final List<HttpMessageConverter<?>> converters;
|
||||
|
||||
/**
|
||||
|
@ -132,7 +143,12 @@ public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>>
|
|||
return false;
|
||||
}
|
||||
}
|
||||
return ClassUtils.isAssignableValue(defaultConverter.getClass(), candidate);
|
||||
Class<?> converterClass = defaultConverter.getClass();
|
||||
if (ClassUtils.isAssignableValue(converterClass, candidate)) {
|
||||
return true;
|
||||
}
|
||||
Class<?> equivalentClass = EQUIVALENT_CONVERTERS.get(converterClass);
|
||||
return equivalentClass != null && ClassUtils.isAssignableValue(equivalentClass, candidate);
|
||||
}
|
||||
|
||||
private void configurePartConverters(AllEncompassingFormHttpMessageConverter formConverter,
|
||||
|
@ -220,4 +236,13 @@ public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>>
|
|||
}
|
||||
}
|
||||
|
||||
private static void putIfExists(Map<Class<?>, Class<?>> map, String keyClassName, String valueClassName) {
|
||||
try {
|
||||
map.put(Class.forName(keyClassName), Class.forName(valueClassName));
|
||||
}
|
||||
catch (ClassNotFoundException | NoClassDefFoundError ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.http;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -28,6 +29,7 @@ import org.springframework.http.converter.ResourceHttpMessageConverter;
|
|||
import org.springframework.http.converter.ResourceRegionHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||
|
@ -81,6 +83,16 @@ class HttpMessageConvertersTests {
|
|||
assertThat(converters.getConverters().indexOf(converter1)).isNotEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addBeforeExistingEquivalentConverter() {
|
||||
GsonHttpMessageConverter converter1 = new GsonHttpMessageConverter();
|
||||
HttpMessageConverters converters = new HttpMessageConverters(converter1);
|
||||
List<Class<?>> converterClasses = converters.getConverters().stream().map(HttpMessageConverter::getClass)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(converterClasses).containsSequence(GsonHttpMessageConverter.class,
|
||||
MappingJackson2HttpMessageConverter.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addNewConverters() {
|
||||
HttpMessageConverter<?> converter1 = mock(HttpMessageConverter.class);
|
||||
|
|
Loading…
Reference in New Issue