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 new file mode 100644 index 00000000000..28e44ad8df4 --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/AbstractJsonParser.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2017 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; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +/** + * Base class for parsers wrapped or implemented in this package. + * + * @author Anton Telechev + */ +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, + Function> parser) { + assert parser != null; + + return trimIfStartsWith(json, START_MAP).map(parser::apply) + .orElseThrow(AbstractJsonParser::cannotParseJson); + } + + /** + * 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); + } + + 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); + } + } + return Optional.empty(); + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java index ab66f625082..b74f8a65001 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java @@ -35,28 +35,16 @@ import org.springframework.util.StringUtils; * @since 1.2.0 * @see JsonParserFactory */ -public class BasicJsonParser implements JsonParser { +public class BasicJsonParser extends AbstractJsonParser { @Override public Map parseMap(String json) { - if (json != null) { - json = json.trim(); - if (json.startsWith("{")) { - return parseMapInternal(json); - } - } - throw new IllegalArgumentException("Cannot parse JSON"); + return parseMap(json, this::parseMapInternal); } @Override public List parseList(String json) { - if (json != null) { - json = json.trim(); - if (json.startsWith("[")) { - return parseListInternal(json); - } - } - throw new IllegalArgumentException("Cannot parse JSON"); + return parseList(json, this::parseListInternal); } private List parseListInternal(String json) { 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 127404421ec..5fd6a123e5e 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 @@ -31,7 +31,7 @@ import com.google.gson.reflect.TypeToken; * @since 1.2.0 * @see JsonParserFactory */ -public class GsonJsonParser implements JsonParser { +public class GsonJsonParser extends AbstractJsonParser { private static final TypeToken MAP_TYPE = new MapTypeToken(); @@ -41,24 +41,14 @@ public class GsonJsonParser implements JsonParser { @Override public Map parseMap(String json) { - if (json != null) { - json = json.trim(); - if (json.startsWith("{")) { - return this.gson.fromJson(json, MAP_TYPE.getType()); - } - } - throw new IllegalArgumentException("Cannot parse JSON"); + return parseMap(json, + (trimmed) -> this.gson.fromJson(trimmed, MAP_TYPE.getType())); } @Override public List parseList(String json) { - if (json != null) { - json = json.trim(); - if (json.startsWith("[")) { - return this.gson.fromJson(json, LIST_TYPE.getType()); - } - } - throw new IllegalArgumentException("Cannot parse JSON"); + return parseList(json, + (trimmed) -> this.gson.fromJson(trimmed, LIST_TYPE.getType())); } private static final class MapTypeToken extends TypeToken> { 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 1d830c834d5..e3c653b87ff 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 @@ -42,7 +42,7 @@ public class JacksonJsonParser implements JsonParser { return getObjectMapper().readValue(json, MAP_TYPE); } catch (Exception ex) { - throw new IllegalArgumentException("Cannot parse JSON", ex); + throw AbstractJsonParser.cannotParseJson(ex); } } @@ -52,7 +52,7 @@ public class JacksonJsonParser implements JsonParser { return getObjectMapper().readValue(json, LIST_TYPE); } catch (Exception ex) { - throw new IllegalArgumentException("Cannot parse JSON", ex); + throw AbstractJsonParser.cannotParseJson(ex); } } 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 80b9bd5447a..1e9e9ce5815 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 @@ -39,7 +39,7 @@ public class JsonSimpleJsonParser implements JsonParser { return (Map) new JSONParser().parse(json); } catch (ParseException ex) { - throw new IllegalArgumentException("Cannot parse JSON", ex); + throw AbstractJsonParser.cannotParseJson(ex); } } @@ -50,7 +50,7 @@ public class JsonSimpleJsonParser implements JsonParser { return (List) new JSONParser().parse(json); } catch (ParseException ex) { - throw new IllegalArgumentException("Cannot parse JSON", ex); + throw AbstractJsonParser.cannotParseJson(ex); } } 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 d2d46536ac5..eb3f13b6b30 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 @@ -28,30 +28,18 @@ import org.yaml.snakeyaml.Yaml; * @author Jean de Klerk * @see JsonParserFactory */ -public class YamlJsonParser implements JsonParser { +public class YamlJsonParser extends AbstractJsonParser { @Override @SuppressWarnings("unchecked") public Map parseMap(String json) { - if (json != null) { - json = json.trim(); - if (json.startsWith("{")) { - return new Yaml().loadAs(json, Map.class); - } - } - throw new IllegalArgumentException("Cannot parse JSON"); + return parseMap(json, (trimmed) -> new Yaml().loadAs(trimmed, Map.class)); } @Override @SuppressWarnings("unchecked") public List parseList(String json) { - if (json != null) { - json = json.trim(); - if (json.startsWith("[")) { - return new Yaml().loadAs(json, List.class); - } - } - throw new IllegalArgumentException("Cannot parse JSON"); + return parseList(json, (trimmed) -> new Yaml().loadAs(trimmed, List.class)); } }