Expressions for manipulating JSON values.
JSONValue
A json-like collection with dynamic keys and values.
Examples
Construct a table with a JSON column
>>> import json, ibis
>>> ibis.options.interactive = True
>>> rows = [{"js" : json.dumps({"a" : [i, 1 ]})} for i in range (2 )]
>>> t = ibis.memtable(rows, schema= ibis.schema(dict (js= "json" )))
>>> t
┏━━━━━━━━━━━━━━┓
┃ js ┃
┡━━━━━━━━━━━━━━┩
│ json │
├──────────────┤
│ { 'a' : [ ... ]} │
│ { 'a' : [ ... ]} │
└──────────────┘
Extract the "a"
field
┏━━━━━━━━━━━━━━━━━━━━━━┓
┃ JSONGetItem(js, 'a') ┃
┡━━━━━━━━━━━━━━━━━━━━━━┩
│ json │
├──────────────────────┤
│ [ 0 , 1 ] │
│ [ 1 , 1 ] │
└──────────────────────┘
Extract the first element of the JSON array at "a"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ JSONGetItem(JSONGetItem(js, 'a'), 0) ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ json │
├──────────────────────────────────────┤
│ 0 │
│ 1 │
└──────────────────────────────────────┘
Extract a non-existent field
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ JSONGetItem(JSONGetItem(js, 'a'), 'foo') ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ json │
├──────────────────────────────────────────┤
│ NULL │
│ NULL │
└──────────────────────────────────────────┘
Try to extract an array element, returns NULL
┏━━━━━━━━━━━━━━━━━━━━━┓
┃ JSONGetItem(js, 20) ┃
┡━━━━━━━━━━━━━━━━━━━━━┩
│ json │
├─────────────────────┤
│ NULL │
│ NULL │
└─────────────────────┘
Attributes
array
Cast JSON to an array of JSON.
bool
Unwrap a JSON value into a backend-native boolean.
float
Unwrap a JSON value into a backend-native float.
int
Unwrap a JSON value into a backend-native int.
map
Cast JSON to a map of string to JSON.
str
Unwrap a JSON string into a backend-native string.
Methods
unwrap_as
Unwrap JSON into a specific data type.
unwrap_as
Unwrap JSON into a specific data type.
Returns
Value
An Ibis expression of a more specific type than JSON
Examples
>>> import ibis
>>> ibis.options.interactive = True
>>> data = {
... "jstring" : ['"a"' , '""' , None , "null" ],
... "jbool" : ["true" , "false" , "null" , None ],
... "jint" : ["1" , "null" , None , "2" ],
... "jfloat" : ["42.42" , None , "null" , "37.37" ],
... "jmap" : ['{"a": 1}' , "null" , None , " {} " ],
... "jarray" : ["[]" , "null" , None , '[ {} ,"1",2]' ],
... }
>>> t = ibis.memtable(data, schema= dict .fromkeys(data.keys(), "json" ))
>>> t
┏━━━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ jstring ┃ jbool ┃ jint ┃ jfloat ┃ jmap ┃ jarray ┃
┡━━━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│ json │ json │ json │ json │ json │ json │
├─────────┼───────┼──────┼────────┼──────────┼──────────────────────┤
│ 'a' │ True │ 1 │ 42.42 │ { 'a' : 1 } │ [] │
│ '' │ False │ None │ NULL │ None │ None │
│ NULL │ None │ NULL │ None │ NULL │ NULL │
│ None │ NULL │ 2 │ 37.37 │ {} │ [{ ... } , '1' , ... +1 ] │
└─────────┴───────┴──────┴────────┴──────────┴──────────────────────┘
>>> t.select(unwrapped= t.jstring.unwrap_as(str ), original= t.jstring)
┏━━━━━━━━━━━┳━━━━━━━━━━┓
┃ unwrapped ┃ original ┃
┡━━━━━━━━━━━╇━━━━━━━━━━┩
│ string │ json │
├───────────┼──────────┤
│ a │ 'a' │
│ ~ │ '' │
│ NULL │ NULL │
│ NULL │ None │
└───────────┴──────────┘
>>> t.select(unwrapped= t.jbool.unwrap_as("bool" ), original= t.jbool)
┏━━━━━━━━━━━┳━━━━━━━━━━┓
┃ unwrapped ┃ original ┃
┡━━━━━━━━━━━╇━━━━━━━━━━┩
│ boolean │ json │
├───────────┼──────────┤
│ True │ True │
│ False │ False │
│ NULL │ None │
│ NULL │ NULL │
└───────────┴──────────┘
>>> t.select(
... unwrapped_int64= t.jint.unwrap_as("int64" ),
... unwrapped_int32= t.jint.unwrap_as("int32" ),
... original= t.jint,
... )
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ unwrapped_int64 ┃ unwrapped_int32 ┃ original ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ int64 │ int32 │ json │
├─────────────────┼─────────────────┼──────────┤
│ 1 │ 1 │ 1 │
│ NULL │ NULL │ None │
│ NULL │ NULL │ NULL │
│ 2 │ 2 │ 2 │
└─────────────────┴─────────────────┴──────────┘
You can cast to a more specific type than the types available in standards-compliant JSON.
Here’s an example of casting JSON numbers to float32
:
>>> t.select(unwrapped= t.jfloat.unwrap_as("float32" ), original= t.jfloat)
┏━━━━━━━━━━━┳━━━━━━━━━━┓
┃ unwrapped ┃ original ┃
┡━━━━━━━━━━━╇━━━━━━━━━━┩
│ float32 │ json │
├───────────┼──────────┤
│ 42.419998 │ 42.42 │
│ NULL │ NULL │
│ NULL │ None │
│ 37.369999 │ 37.37 │
└───────────┴──────────┘
You can cast JSON objects to a more specific map
type:
>>> t.select(unwrapped= t.jmap.unwrap_as("map<string, int>" ), original= t.jmap)
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ unwrapped ┃ original ┃
┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ map<string, int64> │ json │
├────────────────────┼──────────┤
│ { 'a' : 1 } │ { 'a' : 1 } │
│ NULL │ None │
│ NULL │ NULL │
│ {} │ {} │
└────────────────────┴──────────┘
You can cast JSON arrays to an array type as well. In this case the array values don’t have a single element type so we cast to array<json>
.
>>> t.select(unwrapped= t.jarray.unwrap_as("array<json>" ), original= t.jarray)
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ unwrapped ┃ original ┃
┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│ array<json> │ json │
├───────────────────────┼──────────────────────┤
│ [] │ [] │
│ NULL │ None │
│ NULL │ NULL │
│ [ '{}' , '"1"' , ... +1 ] │ [{ ... } , '1' , ... +1 ] │
└───────────────────────┴──────────────────────┘
Back to top