Хочу не прописывать конкретные типы в JSON-маппингах для большей гибкости. Но в коде, конечно, нужно конвертировать в конкретные типы. Для этого написал утилитные методы:
public static int toIntExact(Number n) {
requireNonNull(n, "n");
if (n instanceof BigDecimal bd) {
return bd.intValueExact();
}
if (n instanceof BigInteger bi) {
return bi.intValueExact();
}
if (n instanceof Byte b) {
return b.intValue();
}
if (n instanceof Float f) {
return toIntExact(f.doubleValue());
}
if (n instanceof Double d) {
return toIntExact(d.doubleValue());
}
if (n instanceof Integer i) {
return i;
}
if (n instanceof Long l) {
return Math.toIntExact(l);
}
if (n instanceof Short s) {
return s.intValue();
}
throw new UnsupportedOperationException("Unsupported number class: " + n.getClass().getName());
}
public static Integer toIntegerExact(Number n) {
if (n == null) {
return null;
}
if (n instanceof Integer i) {
return i;
}
return toIntExact(n);
}
public static int toIntExact(double d) {
long l = Math.round(d);
if (l != d) {
throw new ArithmeticException("not int: " + d);
}
return Math.toIntExact(l);
}
public static long toLongValueExact(Number n) {
requireNonNull(n, "n");
if (n instanceof BigDecimal bd) {
return bd.longValueExact();
}
if (n instanceof BigInteger bi) {
return bi.longValueExact();
}
if (n instanceof Byte b) {
return b.longValue();
}
if (n instanceof Float f) {
return toLongValueExact(f.doubleValue());
}
if (n instanceof Double d) {
return toLongValueExact(d.doubleValue());
}
if (n instanceof Integer i) {
return i.longValue();
}
if (n instanceof Long l) {
return l;
}
if (n instanceof Short s) {
return s.longValue();
}
throw new UnsupportedOperationException("Unsupported number class: " + n.getClass().getName());
}
public static Long toLongExact(Number n) {
if (n == null) {
return null;
}
if (n instanceof Long l) {
return l;
}
return toLongValueExact(n);
}
public static long toLongValueExact(double d) {
long l = Math.round(d);
if (l != d) {
throw new ArithmeticException("not int: " + l);
}
return l;
}
Но есть ощущение, что это уже кто-то написал в какой-нибудь популярной библиотеке, но сходу нигде не нашёл.
Number.intValue() не предлагать, оно не кидает ошибку при неверной конвертации, надо кидать.