apache/shenyu · error · JsonParseException

The date should be a string value

Error message

The date should be a string value

What it means

GsonUtils' Timestamp deserializer expects the JSON value to be a JsonPrimitive string formatted as 'yyyy-MM-dd HH:mm:ss'. If the JSON element is not a primitive (object, array, null) it throws JsonParseException with this message, because only a string can be parsed into a Timestamp.

Solutions

  1. Send the date as a quoted string in 'yyyy-MM-dd HH:mm:ss' format.
  2. Make the target field String or a wrapper type and parse manually if the shape can vary.
  3. Register a custom deserializer (or use GsonUtils' built-in one) that handles null/object shapes defensively.
  4. Validate the JSON payload before deserialization.

Example fix

// before
{"createdAt": null}
// after
{"createdAt": "2026-09-12 10:15:30"}
Defensive patterns

Strategy: validation

Validate before calling

JsonElement el = obj.get("createdAt"); if (el == null || !el.isJsonPrimitive() || !el.getAsJsonPrimitive().isString()) throw new IllegalArgumentException("createdAt must be 'yyyy-MM-dd HH:mm:ss' string");

Type guard

boolean isTimestampString(JsonElement el) { return el != null && el.isJsonPrimitive() && el.getAsJsonPrimitive().isString(); }

Try / catch

try { Timestamp ts = gson.fromJson(json, Target.class); } catch (JsonParseException e) { LOG.error("bad timestamp payload", e); }

Prevention

When it happens

Trigger: Deserializing JSON where a field mapped to java.sql.Timestamp is a JSON object/array/null instead of a quoted string, e.g. {"createdAt": {}} or {"createdAt": null} passed through GsonUtils.fromJson with a Timestamp-typed target.

Common situations: Upstream API changed a date field from string to object; sending JSON with null Timestamp field; hand-written JSON forgetting quotes around the date; GraphQL-ish nested payloads fed into admin DTOs.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/296ab7d3bd3736d6. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-common/src/main/java/org/apache/shenyu/common/utils/GsonUtils.java:515

                if (reader.peek() == JsonToken.NULL) {
                    reader.nextNull();
                    return null;
                }
                return Duration.parse(reader.nextString());
            } catch (IOException e) {
                throw new ShenyuException(e);
            }
        }
    }
    
    private static class TimestampTypeAdapter implements JsonSerializer<Timestamp>, JsonDeserializer<Timestamp> {

        private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        @Override
        public Timestamp deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
            if (!(json instanceof JsonPrimitive)) {
                throw new JsonParseException("The date should be a string value");
            }
            try {
                LocalDateTime dateTime = FORMATTER.parse(json.getAsString(), LocalDateTime::from);
                return Timestamp.valueOf(dateTime);
            } catch (Exception e) {
                throw new JsonParseException(e);
            }
        }

        @Override
        public JsonElement serialize(final Timestamp src, final Type typeOfSrc, final JsonSerializationContext context) {
            LocalDateTime ldt = LocalDateTime.ofInstant(src.toInstant(), ZoneId.systemDefault());
            String formatted = FORMATTER.format(ldt);
            return new JsonPrimitive(formatted);
        }
    }
}

View on GitHub (pinned to 567142e072)