Some of you may have experienced this surprising cast. Let me explain it, as there's a good reason for it.
Let's say you have a BigQuery table with an INTEGER field, for exemple "foo" containing 123. Then you export it into a NEWLINE_DELIMITED_JSON file. You expect to get "foo": 123 in your file. And you get "foo": "123". BigQuery cast it to STRING. When you'll ingest it anywhere, then you'll have a STRING. You will experience it when you export it directly with BigQuery, or when you use a table-to-storage Tailer data operation.
The reason is that most JSON parsers support only 32-bit integers, while BQ integers have 64 bits. To avoid any error at the decoding level, BigQuery chose to force to cast all integers to STRING (see documentation for more information).
If you want the JSON to use numbers rather than strings, you can cast the columns in a query to FLOAT64. Note that this option may lose precision, however.
Alternatively, you can use Avro format which supports 64-bit integers.