diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/AbstractJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/AbstractJsonParser.java index 28e44ad8df..c7541292c3 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/AbstractJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/AbstractJsonParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -18,74 +18,49 @@ package org.springframework.boot.json; import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.concurrent.Callable; import java.util.function.Function; +import org.springframework.util.ReflectionUtils; + /** * Base class for parsers wrapped or implemented in this package. * * @author Anton Telechev + * @author Phillip Webb */ abstract class AbstractJsonParser implements JsonParser { - /** Start symbol of a JSON map. **/ - private static final String START_MAP = "{"; - - /** Start symbol of a JSON list. **/ - private static final String START_LIST = "["; - - /** - * Parses the specified JSON string and returns the extracted contents as a Map of - * String to Object. - * - * @param json the JSON string to parse. - * @param parser the parser function. - * @return Map<String, Object> parsed contents - * @throws IllegalArgumentException if the json String cannot be parsed as a - * Map<String, Object> - */ - Map parseMap(String json, + protected final Map parseMap(String json, Function> parser) { - assert parser != null; - - return trimIfStartsWith(json, START_MAP).map(parser::apply) - .orElseThrow(AbstractJsonParser::cannotParseJson); + return trimParse(json, "{", parser); } - /** - * Parses the specified JSON string and returns the extracted contents as a List of Objects. - * - * @param json the JSON string to parse. - * @param parser the parser function. - * @return List<Object> parsed contents - * @throws IllegalArgumentException if the json String cannot be parsed as a - * List<Object> - */ - List parseList(String json, Function> parser) { - assert parser != null; - - return trimIfStartsWith(json, START_LIST).map(parser::apply) - .orElseThrow(AbstractJsonParser::cannotParseJson); + protected final List parseList(String json, + Function> parser) { + return trimParse(json, "[", parser); } - private static IllegalArgumentException cannotParseJson() { - return cannotParseJson(null); - } - - static IllegalArgumentException cannotParseJson(Exception cause) { - return new IllegalArgumentException("Cannot parse JSON", cause); - } - - private static Optional trimIfStartsWith(String json, String expectedPrefix) { - assert expectedPrefix != null; - - if (json != null) { - final String trimmed = json.trim(); - if (trimmed.startsWith(expectedPrefix)) { - return Optional.of(trimmed); - } + protected final T trimParse(String json, String prefix, + Function parser) { + String trimmed = (json == null ? "" : json.trim()); + if (trimmed.startsWith(prefix)) { + return parser.apply(trimmed); + } + throw new JsonParseException(); + } + + protected final T tryParse(Callable parser, Class check) { + try { + return parser.call(); + } + catch (Exception ex) { + if (check.isAssignableFrom(ex.getClass())) { + throw new JsonParseException(ex); + } + ReflectionUtils.rethrowRuntimeException(ex); + throw new IllegalStateException(ex); } - return Optional.empty(); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java index 5fd6a123e5..428645406b 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java index e3c653b87f..41651fa1df 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -28,7 +28,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Dave Syer * @see JsonParserFactory */ -public class JacksonJsonParser implements JsonParser { +public class JacksonJsonParser extends AbstractJsonParser { private static final TypeReference MAP_TYPE = new MapTypeReference(); @@ -38,22 +38,14 @@ public class JacksonJsonParser implements JsonParser { @Override public Map parseMap(String json) { - try { - return getObjectMapper().readValue(json, MAP_TYPE); - } - catch (Exception ex) { - throw AbstractJsonParser.cannotParseJson(ex); - } + return tryParse(() -> getObjectMapper().readValue(json, MAP_TYPE), + Exception.class); } @Override public List parseList(String json) { - try { - return getObjectMapper().readValue(json, LIST_TYPE); - } - catch (Exception ex) { - throw AbstractJsonParser.cannotParseJson(ex); - } + return tryParse(() -> getObjectMapper().readValue(json, LIST_TYPE), + Exception.class); } private ObjectMapper getObjectMapper() { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParseException.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParseException.java new file mode 100644 index 0000000000..10d618fdf9 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParseException.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012-2018 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 + * + * http://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.boot.json; + +/** + * {@link IllegalArgumentException} thrown when source JSON is invalid. + * + * @author Anton Telechev + * @author Phillip Webb + * @since 2.0.1 + */ +public class JsonParseException extends IllegalArgumentException { + + public JsonParseException() { + this(null); + } + + public JsonParseException(Throwable cause) { + super("Cannot parse JSON", cause); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParser.java index 40af726562..c2cdabb158 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -35,14 +35,16 @@ public interface JsonParser { * Parse the specified JSON string into a Map. * @param json the JSON to parse * @return the parsed JSON as a map + * @throws JsonParseException if the JSON cannot be parsed */ - Map parseMap(String json); + Map parseMap(String json) throws JsonParseException; /** * Parse the specified JSON string into a List. * @param json the JSON to parse * @return the parsed JSON as a list + * @throws JsonParseException if the JSON cannot be parsed */ - List parseList(String json); + List parseList(String json) throws JsonParseException; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonSimpleJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonSimpleJsonParser.java index 1e9e9ce581..bdede7e059 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonSimpleJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonSimpleJsonParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -30,28 +30,20 @@ import org.json.simple.parser.ParseException; * @since 1.2.0 * @see JsonParserFactory */ -public class JsonSimpleJsonParser implements JsonParser { +public class JsonSimpleJsonParser extends AbstractJsonParser { @Override @SuppressWarnings("unchecked") public Map parseMap(String json) { - try { - return (Map) new JSONParser().parse(json); - } - catch (ParseException ex) { - throw AbstractJsonParser.cannotParseJson(ex); - } + return (Map) tryParse(() -> new JSONParser().parse(json), + ParseException.class); } @Override @SuppressWarnings("unchecked") public List parseList(String json) { - try { - return (List) new JSONParser().parse(json); - } - catch (ParseException ex) { - throw AbstractJsonParser.cannotParseJson(ex); - } + return (List) tryParse(() -> new JSONParser().parse(json), + ParseException.class); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/YamlJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/YamlJsonParser.java index eb3f13b6b3..14c6f68c87 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/YamlJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/YamlJsonParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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.