@@ -62,7 +62,9 @@ public class JsonMemberDeserVisitor implements ShapeVisitor<Void> {
6262 private final Format timestampFormat ;
6363 private final GoPointableIndex pointableIndex ;
6464
65- public JsonMemberDeserVisitor (GenerationContext context , MemberShape member , String dataDest , Format timestampFormat ) {
65+ public JsonMemberDeserVisitor (
66+ GenerationContext context , MemberShape member , String dataDest , Format timestampFormat
67+ ) {
6668 this .context = context ;
6769 this .member = member ;
6870 this .dataDest = dataDest ;
@@ -147,11 +149,11 @@ public Void longShape(LongShape shape) {
147149
148150 /**
149151 * Deserializes a number without a fractional value.
150- *
152+ * <p>
151153 * The 64-bit integer representation of the number is stored in the variable {@code i64}.
152154 *
153155 * @param shape The shape being deserialized.
154- * @param cast A wrapping of {@code i64} to cast it to the proper type.
156+ * @param cast A wrapping of {@code i64} to cast it to the proper type.
155157 */
156158 private void handleInteger (Shape shape , String cast ) {
157159 GoWriter writer = context .getWriter ();
@@ -164,11 +166,11 @@ private void handleInteger(Shape shape, String cast) {
164166
165167 /**
166168 * Deserializes a json number into a json token.
167- *
169+ * <p>
168170 * The number token is stored under the variable {@code jtv}.
169171 *
170172 * @param shape The shape being deserialized.
171- * @param r A runnable that runs after the value has been parsed, before the scope closes.
173+ * @param r A runnable that runs after the value has been parsed, before the scope closes.
172174 */
173175 private void handleNumber (Shape shape , Runnable r ) {
174176 GoWriter writer = context .getWriter ();
@@ -185,35 +187,91 @@ private void handleNumber(Shape shape, Runnable r) {
185187 });
186188 }
187189
190+ /**
191+ * Deserializes a json arbitrary precision number into a json token.
192+ * <p>
193+ * The number token is stored under the variable {@code jtv}.
194+ *
195+ * @param shape The shape being deserialized.
196+ * @param jsonNumber A runnable that runs after the value has been parsed to a json.Number, before the scope closes.
197+ * @param jsonString A runnable that runs after the value has been parsed to a string, before the scope closes.
198+ */
199+ private void handleDecimal (Shape shape , Runnable jsonNumber , Runnable jsonString ) {
200+ GoWriter writer = context .getWriter ();
201+ ServiceShape service = context .getService ();
202+
203+ writer .addUseImports (SmithyGoDependency .FMT );
204+ writer .openBlock ("if value != nil {" , "}" , () -> {
205+ writer .openBlock ("switch jtv := value.(type) {" , "}" , () -> {
206+ writer .openBlock ("case json.Number:" , "" , jsonNumber );
207+ if (jsonString != null ) {
208+ writer .openBlock ("case string:" , "" , jsonString );
209+ }
210+ writer .openBlock ("default:" , "" , () -> {
211+ writer .write ("return fmt.Errorf(\" expected $L to be a JSON Number, got %T instead\" , value)" ,
212+ shape .getId ().getName (service ));
213+ });
214+ });
215+ });
216+ }
217+
188218 @ Override
189219 public Void floatShape (FloatShape shape ) {
190220 handleFloat (shape , CodegenUtils .getAsPointerIfPointable (context .getModel (), context .getWriter (),
191- pointableIndex , member , "float32(f64)" ));
221+ pointableIndex , member , "float32(f64)" ), true );
192222 return null ;
193223 }
194224
195225 @ Override
196226 public Void doubleShape (DoubleShape shape ) {
197227 handleFloat (shape , CodegenUtils .getAsPointerIfPointable (context .getModel (), context .getWriter (),
198- pointableIndex , member , "f64" ));
228+ pointableIndex , member , "f64" ), true );
199229 return null ;
200230 }
201231
202232 /**
203233 * Deserializes a number with a fractional value.
204- *
234+ * <p>
205235 * The 64-bit float representation of the number is stored in the variable {@code f64}.
206236 *
207237 * @param shape The shape being deserialized.
208- * @param cast A wrapping of {@code f64} to cast it to the proper type.
238+ * @param cast A wrapping of {@code f64} to cast it to the proper type.
209239 */
210- private void handleFloat (Shape shape , String cast ) {
240+ private void handleFloat (Shape shape , String cast , boolean handleNonNumbers ) {
211241 GoWriter writer = context .getWriter ();
212- handleNumber (shape , () -> {
242+
243+ Runnable jsonString = null ;
244+
245+ if (handleNonNumbers ) {
246+ jsonString = () -> {
247+ writer .addUseImports (SmithyGoDependency .STRINGS );
248+ writer .addUseImports (SmithyGoDependency .MATH );
249+
250+ writer .write ("var f64 float64" );
251+ writer .openBlock ("switch {" , "}" , () -> {
252+ writer .openBlock ("case strings.EqualFold(jtv, \" NaN\" ):" , "" , () -> {
253+ writer .write ("f64 = math.NaN()" );
254+ });
255+ writer .openBlock ("case strings.EqualFold(jtv, \" Infinity\" ):" , "" , () -> {
256+ writer .write ("f64 = math.Inf(1)" );
257+ });
258+ writer .openBlock ("case strings.EqualFold(jtv, \" -Infinity\" ):" , "" , () -> {
259+ writer .write ("f64 = math.Inf(-1)" );
260+ });
261+ writer .openBlock ("default:" , "" , () -> {
262+ writer .addUseImports (SmithyGoDependency .FMT );
263+ writer .write ("return fmt.Errorf(\" unknown JSON number value: %s\" , jtv)" );
264+ });
265+ });
266+ writer .write ("$L = $L" , dataDest , cast );
267+ };
268+ }
269+
270+ handleDecimal (shape , () -> {
213271 writer .write ("f64, err := jtv.Float64()" );
214272 writer .write ("if err != nil { return err }" );
215273 writer .write ("$L = $L" , dataDest , cast );
216- });
274+ }, jsonString );
217275 }
218276
219277 @ Override
@@ -233,11 +291,11 @@ public Void stringShape(StringShape shape) {
233291
234292 /**
235293 * Deserializes a json string into a json token.
236- *
294+ * <p>
237295 * The number token is stored under the variable {@code jtv}.
238296 *
239297 * @param shape The shape being deserialized.
240- * @param r A runnable that runs after the value has been parsed, before the scope closes.
298+ * @param r A runnable that runs after the value has been parsed, before the scope closes.
241299 */
242300 private void handleString (Shape shape , Runnable r ) {
243301 GoWriter writer = context .getWriter ();
@@ -279,7 +337,7 @@ public Void timestampShape(TimestampShape shape) {
279337 case EPOCH_SECONDS :
280338 writer .addUseImports (SmithyGoDependency .SMITHY_PTR );
281339 handleFloat (shape , CodegenUtils .getAsPointerIfPointable (context .getModel (), context .getWriter (),
282- pointableIndex , member , "smithytime.ParseEpochSeconds(f64)" ));
340+ pointableIndex , member , "smithytime.ParseEpochSeconds(f64)" ), false );
283341 break ;
284342 default :
285343 throw new CodegenException (String .format ("Unknown timestamp format %s" , timestampFormat ));
0 commit comments