diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2Module.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2Module.java index f3c1d4b24..ee71d5db7 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2Module.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2Module.java @@ -18,6 +18,7 @@ import java.time.Duration; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashSet; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -71,6 +72,7 @@ public void setupModule(SetupContext context) { context.setMixInAnnotations(Collections.unmodifiableMap(Collections.emptyMap()).getClass(), UnmodifiableMapMixin.class); context.setMixInAnnotations(HashSet.class, HashSetMixin.class); + context.setMixInAnnotations(LinkedHashSet.class, HashSetMixin.class); context.setMixInAnnotations(OAuth2AuthorizationRequest.class, OAuth2AuthorizationRequestMixin.class); context.setMixInAnnotations(Duration.class, DurationMixin.class); context.setMixInAnnotations(SignatureAlgorithm.class, SignatureAlgorithmMixin.class); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2ModuleTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2ModuleTests.java new file mode 100644 index 000000000..04898a2ec --- /dev/null +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2ModuleTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2020-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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.server.authorization.jackson2; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link OAuth2AuthorizationServerJackson2Module}. + * + * @author Steve Riesenberg + */ +public class OAuth2AuthorizationServerJackson2ModuleTests { + + private static final TypeReference> STRING_OBJECT_MAP = new TypeReference>() { + }; + private static final TypeReference> STRING_SET = new TypeReference>() { + }; + + private ObjectMapper objectMapper; + + @Before + public void setup() { + this.objectMapper = new ObjectMapper(); + this.objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module()); + } + + @Test + public void readValueWhenUnmodifiableMapThenSuccess() throws Exception { + Map map = Collections.unmodifiableMap(new HashMap<>(Collections.singletonMap("key", "value"))); + String json = this.objectMapper.writeValueAsString(map); + assertThat(this.objectMapper.readValue(json, STRING_OBJECT_MAP)).isEqualTo(map); + } + + @Test + public void readValueWhenHashSetThenSuccess() throws Exception { + Set set = new HashSet<>(Arrays.asList("one", "two")); + String json = this.objectMapper.writeValueAsString(set); + assertThat(this.objectMapper.readValue(json, STRING_SET)).isEqualTo(set); + } + + // gh-457 + @Test + public void readValueWhenLinkedHashSetThenSuccess() throws Exception { + Set set = new LinkedHashSet<>(Arrays.asList("one", "two")); + String json = this.objectMapper.writeValueAsString(set); + assertThat(this.objectMapper.readValue(json, STRING_SET)).isEqualTo(set); + } +}