| | | 1 | | |
| | | 2 | | """ |
| | | 3 | | parse_column_header(token_string)::Pointer |
| | | 4 | | |
| | | 5 | | Parse an Excel column header into a `JSONPointer.Pointer`. |
| | | 6 | | |
| | | 7 | | A leading `/` is added if missing, so both `"a/b"` and `"/a/b"` are accepted. |
| | | 8 | | A trailing `{jsontype}` suffix declares an array element type and produces a |
| | | 9 | | `Pointer{Array{T, 1}}`, where `T` is resolved by `jsontype_to_juliatype`. |
| | | 10 | | Without the suffix, a plain (JSON)`Pointer` is returned. |
| | | 11 | | |
| | | 12 | | # Examples |
| | | 13 | | ```julia |
| | | 14 | | parse_column_header("a/b") # Pointer |
| | | 15 | | parse_column_header("/a/b") # Pointer |
| | | 16 | | parse_column_header("a/b{integer}") # Pointer{Array{Int, 1}} |
| | | 17 | | ``` |
| | | 18 | | """ |
| | 275 | 19 | | function parse_column_header(token_string::AbstractString)::Pointer |
| | 275 | 20 | | if !startswith(token_string, JSONPointer.TOKEN_PREFIX) |
| | 20 | 21 | | token_string = "/" * token_string |
| | | 22 | | end |
| | 275 | 23 | | if endswith(token_string, "}") |
| | 32 | 24 | | x = split(token_string, "{") |
| | 32 | 25 | | p = Pointer(x[1]) |
| | 32 | 26 | | T = jsontype_to_juliatype(x[2][1:end-1]) |
| | | 27 | | |
| | 31 | 28 | | return Pointer{Array{T, 1}}(p.tokens) |
| | | 29 | | else |
| | 243 | 30 | | return Pointer(token_string) |
| | | 31 | | end |
| | | 32 | | end |
| | 0 | 33 | | parse_column_header(token) = parse_column_header(string(token)) |
| | | 34 | | |
| | 42 | 35 | | function jsontype_to_juliatype(t) |
| | 42 | 36 | | if t == "string" |
| | 8 | 37 | | return String |
| | 34 | 38 | | elseif t == "number" |
| | 10 | 39 | | return Float64 |
| | | 40 | | # JSON does not have distinct types for integers and floating-point values |
| | | 41 | | # but Excel does, and distinguishing integer is useful for many things. |
| | 24 | 42 | | elseif t == "integer" |
| | 12 | 43 | | return Int |
| | 12 | 44 | | elseif t == "object" |
| | 2 | 45 | | return OrderedDict{String,Any} |
| | 10 | 46 | | elseif t == "array" |
| | 2 | 47 | | return Vector{Any} |
| | 8 | 48 | | elseif t == "boolean" |
| | 2 | 49 | | return Bool |
| | 6 | 50 | | elseif t == "null" |
| | 2 | 51 | | return Missing |
| | | 52 | | else |
| | 4 | 53 | | error( |
| | | 54 | | "You specified a type that JSON doesn't recognize! Instead of " * |
| | | 55 | | "`::$t`, you must use one of `::string`, `::number`, " * |
| | | 56 | | "`::object`, `::array`, `::boolean`, or `::null`." |
| | | 57 | | ) |
| | | 58 | | end |
| | | 59 | | end |
| | | 60 | | |
| | 32 | 61 | | function pointer_to_colname(p::Pointer{T})::String where T |
| | 32 | 62 | | col = "/" * join(p.tokens, "/") |
| | 32 | 63 | | t = juliatype_to_jsontype(T) |
| | 32 | 64 | | if t == "array" |
| | 4 | 65 | | col *= "::$t" |
| | 4 | 66 | | t2 = juliatype_to_jsontype(eltype(T)) |
| | 4 | 67 | | if !isempty(t2) |
| | 3 | 68 | | col *= "{$t2}" |
| | | 69 | | end |
| | 28 | 70 | | elseif !isempty(t) |
| | 0 | 71 | | col *= "::$t" |
| | | 72 | | end |
| | 32 | 73 | | return col |
| | | 74 | | end |
| | | 75 | | |
| | 47 | 76 | | function juliatype_to_jsontype(T) |
| | 47 | 77 | | if T <: OrderedDict |
| | 1 | 78 | | t = "object" |
| | 46 | 79 | | elseif T <: Array |
| | 6 | 80 | | t = "array" |
| | 40 | 81 | | elseif T == String |
| | 2 | 82 | | t = "string" |
| | 38 | 83 | | elseif T == Float64 |
| | 2 | 84 | | t = "number" |
| | 36 | 85 | | elseif T == Int |
| | 2 | 86 | | t = "integer" |
| | 34 | 87 | | elseif T == Bool |
| | 1 | 88 | | t = "boolean" |
| | 33 | 89 | | elseif T == Missing |
| | 1 | 90 | | t = "null" |
| | 32 | 91 | | elseif T == Nothing |
| | 1 | 92 | | t = "null" |
| | 31 | 93 | | elseif T == Any |
| | 30 | 94 | | t = "" |
| | | 95 | | else |
| | 1 | 96 | | @warn("cannot find jsontype from $T, returning empty string") |
| | 1 | 97 | | t = "" |
| | | 98 | | end |
| | 47 | 99 | | return t |
| | | 100 | | end |