package com.googlecode.totallylazy.json; import com.googlecode.totallylazy.reflection.Reflection; import com.googlecode.totallylazy.reflection.Types; import com.googlecode.totallylazy.time.Dates; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.math.BigDecimal; import java.util.Date; import java.util.List; import java.util.Map; import static com.googlecode.totallylazy.Sequences.sequence; import static com.googlecode.totallylazy.Unchecked.cast; interface Coercer { static Object coerce(Type targetType, Object value) { if (targetType instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) targetType; if (List.class.isAssignableFrom(Types.classOf(parameterizedType))) { Type valueType = parameterizedType.getActualTypeArguments()[0]; return sequence((List<?>) value).map(v -> coerce(valueType, v)).toList(); } } return coerce(Types.classOf(targetType), value); } static Object coerce(Class<?> targetType, Object parsedValue) { if (int.class.isAssignableFrom(targetType) || Integer.class.isAssignableFrom(targetType)) { BigDecimal number = (BigDecimal) parsedValue; return number == null ? null : number.intValue(); } if (long.class.isAssignableFrom(targetType) || Long.class.isAssignableFrom(targetType)) { BigDecimal number = (BigDecimal) parsedValue; return number == null ? null : number.longValue(); } if (JsonRecord.class.isAssignableFrom(targetType) && parsedValue instanceof Map) { return JsonRecord.create(cast(targetType), cast(parsedValue)); } if (targetType.isInterface() && parsedValue instanceof Map) { return PersistentJsonRecord.create(cast(targetType), cast(parsedValue)); } if (Date.class.isAssignableFrom(targetType) && parsedValue instanceof String) { return Dates.parse((String) parsedValue); } if (parsedValue != null && !parsedValue.getClass().isAssignableFrom(targetType)) { return Reflection.valueOf(targetType, parsedValue); } return parsedValue; } }