1 /* 2 * Copyright (C) 2021 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.gson; 18 19 import com.google.gson.internal.LazilyParsedNumber; 20 import com.google.gson.stream.JsonReader; 21 import com.google.gson.stream.MalformedJsonException; 22 import java.io.IOException; 23 import java.math.BigDecimal; 24 25 /** 26 * An enumeration that defines two standard number reading strategies and a couple of 27 * strategies to overcome some historical Gson limitations while deserializing numbers as 28 * {@link Object} and {@link Number}. 29 * 30 * @see ToNumberStrategy 31 * @since 2.8.9 32 */ 33 public enum ToNumberPolicy implements ToNumberStrategy { 34 35 /** 36 * Using this policy will ensure that numbers will be read as {@link Double} values. 37 * This is the default strategy used during deserialization of numbers as {@link Object}. 38 */ 39 DOUBLE { readNumber(JsonReader in)40 @Override public Double readNumber(JsonReader in) throws IOException { 41 return in.nextDouble(); 42 } 43 }, 44 45 /** 46 * Using this policy will ensure that numbers will be read as a lazily parsed number backed 47 * by a string. This is the default strategy used during deserialization of numbers as 48 * {@link Number}. 49 */ 50 LAZILY_PARSED_NUMBER { readNumber(JsonReader in)51 @Override public Number readNumber(JsonReader in) throws IOException { 52 return new LazilyParsedNumber(in.nextString()); 53 } 54 }, 55 56 /** 57 * Using this policy will ensure that numbers will be read as {@link Long} or {@link Double} 58 * values depending on how JSON numbers are represented: {@code Long} if the JSON number can 59 * be parsed as a {@code Long} value, or otherwise {@code Double} if it can be parsed as a 60 * {@code Double} value. If the parsed double-precision number results in a positive or negative 61 * infinity ({@link Double#isInfinite()}) or a NaN ({@link Double#isNaN()}) value and the 62 * {@code JsonReader} is not {@link JsonReader#isLenient() lenient}, a {@link MalformedJsonException} 63 * is thrown. 64 */ 65 LONG_OR_DOUBLE { readNumber(JsonReader in)66 @Override public Number readNumber(JsonReader in) throws IOException, JsonParseException { 67 String value = in.nextString(); 68 try { 69 return Long.parseLong(value); 70 } catch (NumberFormatException longE) { 71 try { 72 Double d = Double.valueOf(value); 73 if ((d.isInfinite() || d.isNaN()) && !in.isLenient()) { 74 throw new MalformedJsonException("JSON forbids NaN and infinities: " + d + "; at path " + in.getPreviousPath()); 75 } 76 return d; 77 } catch (NumberFormatException doubleE) { 78 throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPreviousPath(), doubleE); 79 } 80 } 81 } 82 }, 83 84 /** 85 * Using this policy will ensure that numbers will be read as numbers of arbitrary length 86 * using {@link BigDecimal}. 87 */ 88 BIG_DECIMAL { readNumber(JsonReader in)89 @Override public BigDecimal readNumber(JsonReader in) throws IOException { 90 String value = in.nextString(); 91 try { 92 return new BigDecimal(value); 93 } catch (NumberFormatException e) { 94 throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPreviousPath(), e); 95 } 96 } 97 } 98 99 } 100