Thanks for the report. Unfortunately, this problem is fundamental using TableRow . We highly recommend Solution 1 below: Convert with TableRow as soon as possible into your pipeline.
The TableRow object in which you store these values ββis serialized and deserialized by Jackson, inside the TableRowJsonCoder . Jackson has exactly the behavior you are describing, i.e. for this class:
class MyClass { Object v; }
it will serialize the instance with v = Long.valueOf(<number>) as {v: 30} or {v: 3000000000} . However, during deserialization, it will determine the type of object using the number of bits needed to represent the response. See this SO post .
Two possible solutions come to mind: solution 1 is highly recommended:
Do not use TableRow as an intermediate value. In other words, convert to POJO as soon as possible. The main reason for this mixup type is that TableRow is essentially a Map<String, Object> , and Jackson (or other encoders) may not know that you want to return Long . With POJO types will be clear.
Another advantage of disabling TableRow is to get an efficient encoder, say AvroCoder . Since TableRow encoded and decoded to / from JSON, the encoding is both verbose and slow - shuffling TableRow will be both intensive and intensive using CPU / I / O. I expect you to see much better performance with the help of advised POJOs than if you were going through TableRow objects.
For an example, see LaneInfo in TrafficMaxLaneFlow .
Enter a code that can handle both:
long numberToLong(@Nonnull Number n) { return n.longValue(); } long x = numberToLong((Number) row.get("field")); Long numberToLong(@Nonnull Number n) { if (n instanceof Long) {
You may need additional checks in the second option if n can be null .
source share