How can I make a string from json text when the json text contains many, many quotation marks and string escapes?
For example, the following works:
json_string = """
{
"styles":[
{
"label":"Style",
"target":{
"label":"Target"
},
"overrides":{
"materialProperties":{
"CRYPTO_ID":{
"script":{
"binding":"name"
}
}
}
}
}
]
}
"""
However this does not, due to the escapes:
new_string = """
{
"styles":[
{
"label":"Style",
"target":{
"label":"Target",
"objectName":"*"
},
"overrides":{
"materialProperties":{
"perObj":{
"script":{
"code":"cvex myFn(string myObj=\"\"; export string perObj=\"\") { perObj = myObj; } ",
"bindings":{
"myObj":"myObj"
}
}
}
}
}
}
]
}
"""
Is there a smart way to break this up? I've had no luck breaking it out into chunks and re-assembling to form the same thing when joined and printed.
Your string per se is valid JSON, however Python still sees the \ as special characters.
Use a raw string by prefixing your string with r:
import json
new_string = r"""
{
"styles":[
{
"label":"Style",
"target":{
"label":"Target",
"objectName":"*"
},
"overrides":{
"materialProperties":{
"perObj":{
"script":{
"code":"cvex myFn(string myObj=\"\"; export string perObj=\"\") { perObj = myObj; } ",
"bindings":{
"myObj":"myObj"
}
}
}
}
}
}
]
}
"""
json.loads( new_string )
Or escape your \ characters:
import json
new_string = """
{
"styles":[
{
"label":"Style",
"target":{
"label":"Target",
"objectName":"*"
},
"overrides":{
"materialProperties":{
"perObj":{
"script":{
"code":"cvex myFn(string myObj=\\"\\"; export string perObj=\\"\\") { perObj = myObj; } ",
"bindings":{
"myObj":"myObj"
}
}
}
}
}
}
]
}
"""
json.loads( new_string )
I would recommend reading from an actual JSON file rather than embedding it into your Python code:
with open('path/to/file.json') as f:
json_string = f.read()
Or, if you need the JSON parsed into Python objects (dicts, lists etc.):
import json
with open('path/to/file.json') as f:
json_data = json.load(f)
Related
I am using python 3.6.3a. I would like to generate payload for each of the json records. I am using each variable to access the record. How to assign variable value (each in this case) in payload? I tried {each} and other methods but didn't work.
code snippet below.
json_records = [{"description":"<p>This is scenario1<\/p>","owner":"deb",
"priority":"high"},
{"description":"<p>This is scenario2<\/p>","owner":"deb",
"priority":"medium"}]
json_object = json.loads(json_records)
for each in json_object:
payload = """
{
"subject": "test",
"fieldValues": [
{each}
]
}
"""
There are two ways to approach this problem.
One way could be creating a dict() object and inserting keys as you wish, then json.dumps(object) to convert into string payload as in:
import json
json_records = [{"description":"This is scenario1</p>","owner":"deb","priority":"high"}
,{"description":"This is scenario2</p>","owner":"deb","priority":"medium"}]
for obj in json_records:
payload = dict()
payload['subject'] = 'test'
for key,value in obj.items():
payload['fieldName'] = {
key:value
}
print(json.dumps(payload))
#{"subject": "test", "fieldName": {"priority": "high"}}
#{"subject": "test", "fieldName": {"priority": "medium"}}
Second way is to create a textual payload from string as in, however if you need a valid JSON at the end, this would require a post-step of validation (something like try json.loads(payload) - So I'd just use the first method. I would use this method only if I have a specific requirements to generate the payload in a certain way.
import json
json_records = [{"description":"This is scenario1</p>","owner":"deb","priority":"high"}
,{"description":"This is scenario2</p>","owner":"deb","priority":"medium"}]
# json_object = json.loads(json_records) # json.loads works only on byte-like strings. your object is already in python in this case.
for obj in json_records:
payload = """
{
"subject": "test",
"fieldValues": [
%s
]
}
""" % (obj["priority"])
print(payload)
#{
# "subject": "test",
# "fieldValues": [
# high
# ]
# }
#
#
# {
# "subject": "test",
# "fieldValues": [
# medium
# ]
# }
You could make payload a Template string and use it to put the data in each JSON record into the format you want. Bracket {} characters have not special meaning in Templates, which is what makes using them easy.
Doing that will create a valid string representation of a dictionary containing everything. You can turn this into an actual Python dictionary data-structure using the ast.literal_eval() function, and then convert that into JSON string format — which I think is the final format you're after.
rom ast import literal_eval
import json
from string import Template
from textwrap import dedent
json_records = '''[{"description":"<p>This is scenario1<\/p>","owner":"deb",
"priority":"high"},
{"description":"<p>This is scenario2<\/p>","owner":"deb",
"priority":"medium"}]'''
json_object = json.loads(json_records)
payload = Template(dedent("""
{
"subject": "test",
"fieldValues": [
$each
]
}""")
)
for each in json_object:
obj = literal_eval(payload.substitute(dict(each=each)))
print(json.dumps(obj, indent=2))
Output:
{
"subject": "test",
"fieldValues": [
{
"description": "<p>This is scenario1</p>",
"owner": "deb",
"priority": "high"
}
]
}
{
"subject": "test",
"fieldValues": [
{
"description": "<p>This is scenario2</p>",
"owner": "deb",
"priority": "medium"
}
]
}
following Update json nodes in Python using jsonpath, would like to know how one might update the JSON data given a certain context.
So, say we pick the exact same JSON example:
{
"SchemeId": 10,
"nominations": [
{
"nominationId": 1
}
]
}
But this time, would like to double the value of the original value, hence some lambda function is needed which takes into account the current node value.
No need for lambdas; for example, to double SchemeId, something like this should work:
data = json.loads("""the json string above""")
jsonpath_expr = parse('$.SchemeId')
jsonpath_expr.find(data)
val = jsonpath_expr.find(data)[0].value
jsonpath_expr.update(data, val*2)
print(json.dumps(data, indent=2))
Output:
{
"SchemeId": 20,
"nominations": [
{
"nominationId": 1
}
]
}
Here is example with lambda expression:
import json
from jsonpath_ng import parse
settings = '''{
"choices": {
"atm": {
"cs": "Strom",
"en": "Tree"
},
"bar": {
"cs": "Dům",
"en": "House"
},
"sea": {
"cs": "Moře",
"en": "Sea"
}
}
}'''
json_data = json.loads(settings)
pattern = parse('$.choices.*')
def magic(f: dict, to_lang='cs'):
return f[to_lang]
pattern.update(json_data,
lambda data_field, data, field: data.update({field: magic(data[field])}))
json_data
returns
{
'choices': {
'atm': 'Strom',
'bar': 'Dům',
'sea': 'Moře'
}
}
I have a JSON file as follows :
{
"desired":{
"property1":{
"port":"/dev/usbserial",
"rx":{
"watchdoginterval":3600
},
"state":{
"path":"/Users/user1"
},
"enabled":"true",
"active":{
"enabled":"true"
}
},
"property2":{
"signal_interrupt":"USR2",
"signal_description_path":"/tmp/logger.log"
},
"property3":{
"periodmins":40
},
}
}
I am having issues trying to convert this into a string for use with AWS IoT. The function I am using is deviceShadowHandler.shadowUpdate(JSONPayload, customShadowCallback_Update, 5)
Where JSONPayload should be the JSON string.
I have tried :
with open('JSONfile.json' , 'r') as f:
dict = json.load(f)
JSONPayload = str(dict)
but I receive an "Invalid JSON file error".
An attempt to manually create a literal string from the jSON file gets messy with complaints about "EOL while scanning string literal" etc.
What is the best solution to solve this? I am new to JSON and stuff and Python.
Trailing commas are not allowed in JSON.
{
"desired":{
"property1":{
"port":"/dev/usbserial",
"rx":{
"watchdoginterval":3600
},
"state":{
"path":"/Users/user1"
},
"enabled":"true",
"active":{
"enabled":"true"
}
},
"property2":{
"signal_interrupt":"USR2",
"signal_description_path":"/tmp/logger.log"
},
"property3":{
"periodmins":40
} # <- no comma there
}
}
I have the following Json file: car_models.json
{
"name":"John",
"age":30,
"cars":
[
{
"car_model": "Mustang",
"car_brand": "Ford"
},
{
"car_model": "cx-5",
"car_brand": "Mazda"
}
]
}
I have another json file data_change.json, which contains details about the jsonpath and their values:
{
"testcase_ID": "test_1A",
"description": "Some description",
"request_change_data": [
{
"element_path": "$.cars.[0].car_model",
"element_value": "focus"
}
]
}
I want to read the data_change.json content, use the element_path from here, parse through car_models.json and update its value to the value from data_change.json.
As in, I want to use the jsonPath - $cars[0].car_model, parse through car_models.json, and change the value of car_model from Mustang to focus. So my updated car_models.json should be the following:
{
"name":"John",
"age":30,
"cars":
[
{
"car_model": "focus",
"car_brand": "Ford"
},
{
"car_model": "cx-5",
"car_brand": "Mazda"
}
]
}
How can I do this in python?
guessing that the Expected answer needs to have "focus" and not "ford"
The following should give you this:
import json
import re
with open('cars_model.json') as f:
cars_model = json.load(f)
with open('data_change.json') as f:
data_change = json.load(f)
for elements in data_change['request_change_data']:
element_path = elements['element_path']
#Reg ex to get you the number (as a string) between the square brackets
position_match = re.match(r"^.*\[(.*)\].*$", element_path)
position = int(position_match.group(1))
print position
# Split on "period" to get the thing to match
thing_to_change = element_path.split(".")[1]
print thing_to_change
value = elements['element_value']
print value
cars_model['cars'][0][thing_to_change] = value
print cars_model
i have a following json file
json_data = {
"action":"postRecord",
"data":{
"data":[
{
"info":{
"lid":999,
"cid":1234
},
"info":{
"lid":111,
"cid":"6789"
}
}
]
}
}
i tried the usage of json.load
output = json.load(json_data)
but it returnign a string
i want to access the value of id in a way like output['data']['data']['info']['id']
Isn't your data already in the format you want?
print json_data['data']['data'][0]['info']['cid']
Uh. You're saying that you've got an JSON array as a plain text in a json_data variable?
You should put the JSON data into the json_data variable as a string and use json.loads(json_data).
Since JSON is just text, you should treat it like a string, unless you have opened a JSON file from the disk, then json.load() should work with the file object itself.
In [5]: json_data = '{ "action":"postRecord", "data":{ "data":[ { "info":{ "lid":999, "cid":1234 }, "info":{ "lid":111, "cid":"6789" } } ] } }'
In [6]: output = json.loads(json_data)
In [7]: output['data']['data'][0]['info']['cid']
Out[7]: u'6789'
seems the original json string has problem, there has duplicate info property in one element, so after json.dump to format , the first info will be removed , and the result is the second 6789.
json_data = { "action":"postRecord", "data":{ "data":[ { "info":{ "lid":999, "cid":1234 }, "info":{ "lid":111, "cid":"6789" } } ] } }
data = json.dumps(json_data)
json_to_python = json.loads(data)
print (json_to_python)
print (json_to_python['data']['data'][0]['info']['cid'])
======>
{'action': 'postRecord', 'data': {'data': [{'info1': {'lid': 999, 'cid': 1234}, 'info': {'lid': 111, 'cid': '6789'}}]}}
6789