@@ -26,6 +26,15 @@ cdef extern from "jv.h":
2626 int jv_invalid_has_msg(jv)
2727 char * jv_string_value(jv)
2828 jv jv_dump_string(jv, int flags)
29+ int jv_is_integer(jv)
30+ double jv_number_value(jv)
31+ int jv_array_length(jv)
32+ jv jv_array_get(jv, int )
33+ int jv_object_iter(jv)
34+ int jv_object_iter_next(jv, int )
35+ int jv_object_iter_valid(jv, int )
36+ jv jv_object_iter_key(jv, int )
37+ jv jv_object_iter_value(jv, int )
2938
3039 cdef struct jv_parser:
3140 pass
@@ -51,6 +60,52 @@ cdef extern from "jq.h":
5160 void jq_get_error_cb(jq_state * , jq_err_cb * , void ** )
5261
5362
63+ cdef object _jv_to_python(jv value):
64+ """ Unpack a jv value into a Python value"""
65+ cdef jv_kind kind = jv_get_kind(value)
66+ cdef int idx
67+ cdef jv property_key
68+ cdef jv property_value
69+ cdef object python_value
70+
71+ if kind == JV_KIND_INVALID:
72+ raise ValueError (" Invalid value" )
73+ elif kind == JV_KIND_NULL:
74+ python_value = None
75+ elif kind == JV_KIND_FALSE:
76+ python_value = False
77+ elif kind == JV_KIND_TRUE:
78+ python_value = True
79+ elif kind == JV_KIND_NUMBER:
80+ if jv_is_integer(value):
81+ python_value = int (jv_number_value(value))
82+ else :
83+ python_value = float (jv_number_value(value))
84+ elif kind == JV_KIND_STRING:
85+ python_value = jv_string_value(value).decode(" utf-8" )
86+ elif kind == JV_KIND_ARRAY:
87+ python_value = []
88+ for idx in range (0 , jv_array_length(jv_copy(value))):
89+ property_value = jv_array_get(jv_copy(value), idx)
90+ python_value.append(_jv_to_python(property_value))
91+ elif kind == JV_KIND_OBJECT:
92+ python_value = {}
93+ idx = jv_object_iter(value)
94+ while jv_object_iter_valid(value, idx):
95+ property_key = jv_object_iter_key(value, idx)
96+ property_value = jv_object_iter_value(value, idx)
97+ try :
98+ python_value[jv_string_value(property_key).decode(" utf-8" )] = \
99+ _jv_to_python(property_value)
100+ finally :
101+ jv_free(property_key)
102+ idx = jv_object_iter_next(value, idx)
103+ else :
104+ raise ValueError (" Invalid value kind: " + str (kind))
105+ jv_free(value)
106+ return python_value
107+
108+
54109def compile (object program ):
55110 cdef object program_bytes = program.encode(" utf8" )
56111 return _Program(program_bytes)
@@ -199,13 +254,7 @@ cdef class _ProgramWithInput(object):
199254 return _ResultIterator(self ._jq_state_pool, self ._bytes_input)
200255
201256 def text (self ):
202- iterator = self ._make_iterator()
203- results = []
204- while True :
205- try :
206- results.append(iterator._next_string())
207- except StopIteration :
208- return " \n " .join(results)
257+ return " \n " .join(json.dumps(v) for v in self )
209258
210259 def all (self ):
211260 return list (self )
@@ -239,9 +288,6 @@ cdef class _ResultIterator(object):
239288 return self
240289
241290 def __next__ (self ):
242- return json.loads(self ._next_string())
243-
244- cdef unicode _next_string(self ):
245291 cdef int dumpopts = 0
246292 while True :
247293 if not self ._ready:
@@ -250,10 +296,7 @@ cdef class _ResultIterator(object):
250296
251297 result = jq_next(self ._jq)
252298 if jv_is_valid(result):
253- dumped = jv_dump_string(result, dumpopts)
254- value = jv_string_value(dumped).decode(" utf8" )
255- jv_free(dumped)
256- return value
299+ return _jv_to_python(result)
257300 elif jv_invalid_has_msg(jv_copy(result)):
258301 error_message = jv_invalid_get_msg(result)
259302 message = jv_string_value(error_message).decode(" utf8" )
0 commit comments