forked from apache/arrow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
json.R
124 lines (118 loc) · 4.55 KB
/
json.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#' Read a JSON file
#'
#' Wrapper around [JsonTableReader] to read a newline-delimited JSON (ndjson) file into a
#' data frame or Arrow Table.
#'
#' If passed a path, will detect and handle compression from the file extension
#' (e.g. `.json.gz`).
#'
#' If `schema` is not provided, Arrow data types are inferred from the data:
#' - JSON null values convert to the [null()] type, but can fall back to any other type.
#' - JSON booleans convert to [boolean()].
#' - JSON numbers convert to [int64()], falling back to [float64()] if a non-integer is encountered.
#' - JSON strings of the kind "YYYY-MM-DD" and "YYYY-MM-DD hh:mm:ss" convert to [`timestamp(unit = "s")`][timestamp()],
#' falling back to [utf8()] if a conversion error occurs.
#' - JSON arrays convert to a [list_of()] type, and inference proceeds recursively on the JSON arrays' values.
#' - Nested JSON objects convert to a [struct()] type, and inference proceeds recursively on the JSON objects' values.
#'
#' When `as_data_frame = FALSE`, Arrow types are further converted to R types.
#' See \url{https://arrow.apache.org/docs/r/articles/read_write.html} for details.
#'
#' @inheritParams read_delim_arrow
#' @param schema [Schema] that describes the table.
#' @param ... Additional options passed to `JsonTableReader$create()`
#'
#' @return A `data.frame`, or a Table if `as_data_frame = FALSE`.
#' @export
#' @examplesIf arrow_with_json()
#' tf <- tempfile()
#' on.exit(unlink(tf))
#' writeLines('
#' { "hello": 3.5, "world": false, "yo": "thing" }
#' { "hello": 3.25, "world": null }
#' { "hello": 0.0, "world": true, "yo": null }
#' ', tf, useBytes = TRUE)
#' read_json_arrow(tf)
read_json_arrow <- function(file,
col_select = NULL,
as_data_frame = TRUE,
schema = NULL,
...) {
if (!inherits(file, "InputStream")) {
compression <- detect_compression(file)
file <- make_readable_file(file)
if (compression != "uncompressed") {
# TODO: accept compression and compression_level as args
file <- CompressedInputStream$create(file, compression)
}
on.exit(file$close())
}
tab <- JsonTableReader$create(file, schema = schema, ...)$Read()
col_select <- enquo(col_select)
if (!quo_is_null(col_select)) {
sim_df <- as.data.frame(tab$schema)
tab <- tab[eval_select(col_select, sim_df)]
}
if (isTRUE(as_data_frame)) {
tab <- as.data.frame(tab)
}
tab
}
#' @include arrow-object.R
#' @rdname CsvTableReader
#' @usage NULL
#' @format NULL
#' @docType class
#' @export
JsonTableReader <- R6Class("JsonTableReader",
inherit = ArrowObject,
public = list(
Read = function() json___TableReader__Read(self)
)
)
JsonTableReader$create <- function(file,
read_options = JsonReadOptions$create(),
parse_options = JsonParseOptions$create(schema = schema),
schema = NULL,
...) {
assert_is(file, "InputStream")
json___TableReader__Make(file, read_options, parse_options)
}
#' @rdname CsvReadOptions
#' @usage NULL
#' @format NULL
#' @docType class
#' @export
JsonReadOptions <- R6Class("JsonReadOptions", inherit = ArrowObject)
JsonReadOptions$create <- function(use_threads = option_use_threads(), block_size = 1048576L) {
json___ReadOptions__initialize(use_threads, block_size)
}
#' @rdname CsvReadOptions
#' @usage NULL
#' @format NULL
#' @docType class
#' @export
JsonParseOptions <- R6Class("JsonParseOptions", inherit = ArrowObject)
JsonParseOptions$create <- function(newlines_in_values = FALSE, schema = NULL) {
if (is.null(schema)) {
json___ParseOptions__initialize1(newlines_in_values)
} else {
json___ParseOptions__initialize2(newlines_in_values, schema)
}
}