11# -*- coding: utf-8 -*-
2+ import io
23import json
34import os .path
45from robot .api import logger
56from robot .api .deco import keyword
6- from jsonpath_rw import Index , Fields
7- from jsonpath_rw_ext import parse
7+ from robot .utils .asserts import assert_true , fail
8+ from jsonpath_ng import Index , Fields
9+ from jsonpath_ng .ext import parse
810from .version import VERSION
911
1012__author__ = 'Traitanit Huangsri'
@@ -16,13 +18,14 @@ class JSONLibraryKeywords(object):
1618 ROBOT_EXIT_ON_FAILURE = True
1719
1820 @keyword ('Load JSON From File' )
19- def load_json_from_file (self , file_name ):
21+ def load_json_from_file (self , file_name , encoding = None ):
2022 """Load JSON from file.
2123
2224 Return json as a dictionary object.
2325
2426 Arguments:
2527 - file_name: absolute json file name
28+ - encoding: encoding of the file
2629
2730 Return json object (list or dictionary)
2831
@@ -33,7 +36,7 @@ def load_json_from_file(self, file_name):
3336 if os .path .isfile (file_name ) is False :
3437 logger .error ("JSON file: " + file_name + " not found" )
3538 raise IOError
36- with open (file_name ) as json_file :
39+ with io . open (file_name , mode = 'r' , encoding = encoding ) as json_file :
3740 data = json .load (json_file )
3841 return data
3942
@@ -53,11 +56,23 @@ def add_object_to_json(self, json_object, json_path, object_to_add):
5356 | ${json}= | Add Object To Json | ${json} | $..address | ${dict} |
5457 """
5558 json_path_expr = parse (json_path )
56- for match in json_path_expr .find (json_object ):
57- if type (match .value ) is dict :
58- match .value .update (object_to_add )
59- if type (match .value ) is list :
60- match .value .append (object_to_add )
59+ rv = json_path_expr .find (json_object )
60+ if len (rv ):
61+ for match in rv :
62+ if type (match .value ) is dict :
63+ match .value .update (object_to_add )
64+ if type (match .value ) is list :
65+ match .value .append (object_to_add )
66+ else :
67+ parent_json_path = '.' .join (json_path .split ('.' )[:- 1 ])
68+ child_name = json_path .split ('.' )[- 1 ]
69+ json_path_expr = parse (parent_json_path )
70+ rv = json_path_expr .find (json_object )
71+ if len (rv ):
72+ for match in rv :
73+ match .value .update ({child_name :object_to_add })
74+ else :
75+ fail (f"no match found for parent { parent_json_path } " )
6176
6277 return json_object
6378
@@ -75,7 +90,11 @@ def get_value_from_json(self, json_object, json_path):
7590 | ${values}= | Get Value From Json | ${json} | $..phone_number |
7691 """
7792 json_path_expr = parse (json_path )
78- return [match .value for match in json_path_expr .find (json_object )]
93+ rv = json_path_expr .find (json_object )
94+ # make the keyword fails if nothing was return
95+ assert_true (rv is not None and len (rv )!= 0 ,
96+ f"Get Value From Json keyword failed to find a value for { json_path } " )
97+ return [match .value for match in rv ]
7998
8099 @keyword ('Update Value To Json' )
81100 def update_value_to_json (self , json_object , json_path , new_value ):
@@ -114,7 +133,7 @@ def delete_object_from_json(self, json_object, json_path):
114133 | ${json_object}= | Delete Object From Json | ${json} | $..address.streetAddress |
115134 """
116135 json_path_expr = parse (json_path )
117- for match in json_path_expr .find (json_object ):
136+ for match in reversed ( json_path_expr .find (json_object ) ):
118137 path = match .path
119138 if isinstance (path , Index ):
120139 del (match .context .value [match .path .index ])
@@ -136,7 +155,7 @@ def convert_json_to_string(self, json_object):
136155 """
137156 return json .dumps (json_object )
138157
139- @keyword ('Convert String to JSON' )
158+ @keyword ('Convert String To JSON' )
140159 def convert_string_to_json (self , json_string ):
141160 """Convert String to JSON object
142161
@@ -150,3 +169,60 @@ def convert_string_to_json(self, json_string):
150169 """
151170 return json .loads (json_string )
152171
172+ @keyword ('Dump JSON To File' )
173+ def dump_json_to_file (self , dest_file , json_object ):
174+ """Dump JSON to file
175+
176+ Arguments:
177+ - dest_file: destination file
178+ - json_object: json as a dictionary object.
179+
180+ Export the JSON object to a file
181+
182+ Examples:
183+ | Dump JSON To File | ${OUTPUTID)${/}output.json | ${json} |
184+ """
185+ json_str = self .convert_json_to_string (json_object )
186+ with open (dest_file , "w" ) as json_file :
187+ json_file .write (json_str )
188+ return str (dest_file )
189+
190+ @keyword ('Should Have Value In Json' )
191+ def should_have_value_in_json (self , json_object , json_path ):
192+ """Should Have Value In JSON using JSONPath
193+
194+ Arguments:
195+ - json_object: json as a dictionary object.
196+ - json_path: jsonpath expression
197+
198+ Fail if no value is found
199+
200+ Examples:
201+ | Should Have Value In Json | ${json} | $..id_card_number |
202+ """
203+ try :
204+ self .get_value_from_json (json_object , json_path )
205+ except AssertionError :
206+ fail (f"No value found for path { json_path } " )
207+
208+
209+ @keyword ('Should Not Have Value In Json' )
210+ def should_not_have_value_in_json (self , json_object , json_path ):
211+ """Should Not Have Value In JSON using JSONPath
212+
213+ Arguments:
214+ - json_object: json as a dictionary object.
215+ - json_path: jsonpath expression
216+
217+ Fail if at least one value is found
218+
219+ Examples:
220+ | Should Not Have Value In Json | ${json} | $..id_card_number |
221+ """
222+ try :
223+ rv = self .get_value_from_json (json_object , json_path )
224+ except AssertionError :
225+ pass
226+ else :
227+ fail (f"Match found for parent { json_path } : { rv } " )
228+
0 commit comments