chinabugotech/hutool · error · ConvertException

Unsupported type: [{}] from map: [{}]

Error message

Unsupported type: [{}] from map: [{}]

What it means

Thrown by TemporalAccessorConverter.convertInternal() when the input value is a Map but the target java.time type is not LocalDate, LocalDateTime, or LocalTime. The Map branch only handles those three types; other temporal types like OffsetDateTime, ZonedDateTime, OffsetTime, Year, YearMonth, Instant, etc., are unsupported when the source is a Map.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/convert/impl/TemporalAccessorConverter.java:124

		} else if (value instanceof TemporalAccessor) {
			return parseFromTemporalAccessor((TemporalAccessor) value);
		} else if (value instanceof Date) {
			final DateTime dateTime = DateUtil.date((Date) value);
			return parseFromInstant(dateTime.toInstant(), dateTime.getZoneId());
		} else if (value instanceof Calendar) {
			final Calendar calendar = (Calendar) value;
			return parseFromInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());
		} else if (value instanceof Map) {
			final Map<?, ?> map = (Map<?, ?>) value;
			if (LocalDate.class.equals(this.targetType)) {
				return LocalDate.of(Convert.toInt(map.get("year")), Convert.toInt(map.get("month")), Convert.toInt(map.get("day")));
			} else if (LocalDateTime.class.equals(this.targetType)) {
				return LocalDateTime.of(Convert.toInt(map.get("year")), Convert.toInt(map.get("month")), Convert.toInt(map.get("day")),
					Convert.toInt(map.get("hour")), Convert.toInt(map.get("minute")), Convert.toInt(map.get("second")), Convert.toInt(map.get("second")));
			} else if (LocalTime.class.equals(this.targetType)) {
				return LocalTime.of(Convert.toInt(map.get("hour")), Convert.toInt(map.get("minute")), Convert.toInt(map.get("second")), Convert.toInt(map.get("nano")));
			}
			throw new ConvertException("Unsupported type: [{}] from map: [{}]", this.targetType, map);
		} else {
			return parseFromCharSequence(convertToStr(value));
		}
	}

	/**
	 * 通过反射从字符串转java.time中的对象
	 *
	 * @param value 字符串值
	 * @return 日期对象
	 */
	private TemporalAccessor parseFromCharSequence(CharSequence value) {
		if (StrUtil.isBlank(value)) {
			return null;
		}

		if (DayOfWeek.class.equals(this.targetType)) {
			return DayOfWeek.valueOf(StrUtil.toString(value));

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Convert the Map to a String (ISO-8601 format) first, then convert the String to the temporal type: OffsetDateTime.parse(str).
  2. Build the target temporal object manually from the Map entries instead of using the converter.
  3. If the target is one of the supported three (LocalDate, LocalDateTime, LocalTime), ensure the Map keys are year/month/day/hour/minute/second/nano as expected.
  4. Register a custom converter for the specific temporal type you need.

Example fix

// before
OffsetDateTime odt = Convert.convert(OffsetDateTime.class, dateMap); // throws

// after
LocalDateTime ldt = Convert.convert(LocalDateTime.class, dateMap);
OffsetDateTime odt = ldt.atOffset(ZoneOffset.ofHours(8));
Defensive patterns

Strategy: validation

Validate before calling

if (value instanceof Map &&
    targetType != LocalDate.class && targetType != LocalDateTime.class
    && targetType != LocalTime.class) {
    // convert map to a string or build temporal manually
    throw new IllegalArgumentException("Map source only supports LocalDate, LocalDateTime, LocalTime");
}

Type guard

static boolean supportsMapSource(Class<?> temporalType) {
    return temporalType == LocalDate.class
        || temporalType == LocalDateTime.class
        || temporalType == LocalTime.class;
}

Try / catch

try {
    return Convert.convert(targetType, mapValue);
} catch (ConvertException e) {
    if (e.getMessage().contains("Unsupported type") && value instanceof Map) {
        // fallback: convert to string first, then parse
        return Convert.convert(targetType, mapValue.toString());
    }
    throw e;
}

Prevention

When it happens

Trigger: Convert.convert(OffsetDateTime.class, mapWithDateFields). Convert.convert(ZonedDateTime.class, jsonMap). Convert.convert(Year.class, map). Passing a Map to any temporal type not in {LocalDate, LocalDateTime, LocalTime}.

Common situations: Deserializing JSON maps into OffsetDateTime or ZonedDateTime fields of a DTO. Converting database row maps into temporal types beyond the three locals. ORM or JSON frameworks that produce Map<String,Object> and rely on Hutool for temporal conversion.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/2f3d47ded803ba12. Report an issue: GitHub.