Access JSON element with parent name unknown - python

I've got the same extact problem with Access JSON item when parent key name is unknown, but I work in python.
{
"query": {
"pages": {
"ramdom_number_here": {
"pageid": ramdom_number_here,
"ns": 0,
"title": "Hello",
"extract": "Hello world! Enchanté to meet you"
}
}
}
}
How to get extract given the random_number changing every time?
p.s. It's quite a duplicate question and I'm not sure if the best thing is to open a new question or to answer under the other.

In this case, the key doesn't matter. You just want the (only) value stored in the pages object.
pages = d['query']['pages'].values()
x = list(pages)[0]['extract']

Related

How to get value off JSON in Robot framework

I have for example a log that will change each time it is run an example is below. I will like to take one of the value(id) lets say as a variable and log only the id to console or use that value somewhere else.
[
{
"#type": "type",
"href": [
{
"#url": "url1",
"#method": "get"
},
{
"#url": "url2",
"#method": "post"
},
{
"#url": "url3",
"#method": "post"
}
],
"id": "3",
"meta": [
{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
}
]
}
]
I want to get the id in a variable because the id changes after each time the robot framework is ran
You can see here that the JSON you are getting is in list format. Which means that to get a value from the JSON, you'll first need to read the JSON object in, then get the dictionary out of the list and only then access the key value you'd need to extract.
Robot Framework supports using Python statements with Evaluate keyword. When we need to simply parse some string to JSON we can get by using
${DATA}= Evaluate json.loads("""${DATA}""")
Notice that the ${DATA} here should contain your JSON as a string.
Now that we have the JSON object, we can do whatever we want with it. We can actually see from your JSON that it is actually a dictionary nested inside a list object (See surrounding []). So first, extract dictionary from the list, then access the dictionary key normally. The following should work fine.
${DICT}= Get From List ${DATA} 0
${ID}= Get From Dictionary ${DICT} id

Alexa: How to assign a slot response to a variable. (Python)

I'm not sure how to assign a slot to a variable in an Alexa skill. I've found several tutorials, but most of them are in JS (I wrote this code in Python) or outdated, since even using them precisely as presented does not work.
Alexa is meant to ask for one of my kids' names so I can implement a personalized answer, but I can't find a way to make use of the name once she gets it.
Here's how I call it in my code (look at variable "kids_name" in particular):
#sb.request_handler(can_handle_func=lambda input:
currently_playing(input) and
is_intent_name("ChoresIntent")(input))
def chores_intent_handler(handler_input):
session_attr = handler_input.attributes_manager.session_attributes
original_date = date(2022, 4, 8)
today = date.today()
diff = (today - original_date).days
kids_name = handler_input.request_envelope.request.intent.slots.name.value
mod = "Error. No input."
That seemed to be how they set the variable in the most recent tutorial I found, but it absolutely will not run for me. I've watched tutorials on pulling data from JSON files, but none of their answers look anything like this.
As I understand it, I construct the path from JSON, but I don't understand the syntax. Here's the JSON for my skill. I would really appreciate some clarification on how to transfer handler answers from one to the other. While I think I get the basic structure of the dictionaries, the methods I see for accessing them is very confusing for me.
{
"name": "ChoresIntent",
"slots": [
{
"name": "childname",
"type": "childname"
}
],
"samples": [
"what are {childname} s jobs today",
"what are my jobs today",
"can you tell me {childname} s chores",
]
}
],
"types": [
{
"name": "childname",
"values": [
{
"name": {
"value": "Matthew",
"synonyms": [
"Mattie"
]
}
},
Thank you in advance! I really appreciate the help I get on here.
You have 2 options
Without ask_sdk:
kids_name = handler_input.request_envelope.request.intent.slots["name"].value
With ask_sdk:
kids_name = ask_utils.request_util.get_slot_value(handler_input, "name")
# You can also get the slot and then set the value:
slotName = ask_utils.request_util.get_slot(handler_input, "name")
kids_name = slotName.value

Using Bad Json in Python

I am having a json in a file which i want to access in my Python Code. The Json file looks like :
{
"fc1" : {
region : "Delhi",
marketplace : "IN"
},
"fc2" : {
region : "Rajasthan",
marketplace : "IN"
}
}
The above json i want to use in my Python code. I want to access according to its keys("fc1", "fc2")
Since this is not like actual json, i am facing difficulty in accessing the values in json.
Is there any way in python language to access these type of json.
Thanks.
I agree with the comment that, if you generated that file, then you should put quotes around region and marketplace when generating it (or have the person who generated it do the same). However, if this absolutely isn't an option for whatever reason, the following approach might work:
import json
data_string = """
{
"fc1":{
region:"Delhi",
marketplace: "IN"
},
"fc2" : {
region:"Rajasthan",
marketplace: "IN"
}
}
"""
data = json.loads(data_string.replace('region', '"region"').replace('marketplace', '"marketplace"'))
data
>>>{'fc1': {'region': 'Delhi', 'marketplace': 'IN'},
'fc2': {'region': 'Rajasthan', 'marketplace': 'IN'}}
Note that you would have to do the same for any unquoted key.
There is module dirtyjson which reads this incorrect JSON.
import dirtyjson
data_string = """
{
"fc1":{
region:"Delhi",
marketplace: "IN"
},
"fc2" : {
region:"Rajasthan",
marketplace: "IN"
}
}
"""
data = dirtyjson.loads(data_string)
print(data)
print(data['fc1'])
print(data['fc2'])

Change the font of an entire document without affecting formatting using Google Docs API

I am trying to change the font of an entire Google Doc using the API. The purpose is to let users of our application export documents with their company’s font.
This is what I am currently doing:
from googleapiclient.discovery import build
doc_service = build("docs", "v1")
document = self.doc_service.documents().get(documentId="[Document ID]").execute()
requests = []
for element in document["body"]["content"]:
if "sectionBreak" in element:
continue # Trying to change the font of a section break causes an error
requests.append(
{
"updateTextStyle": {
"range": {
"startIndex": element["startIndex"],
"endIndex": element["endIndex"],
},
"textStyle": {
"weightedFontFamily": {
"fontFamily": "[Font name]"
},
},
"fields": "weightedFontFamily",
}
}
)
doc_service.documents().batchUpdate(
documentId=self.copy_id, body={"requests": requests}
).execute()
The code above changes the font, but it also removes any bold text formatting because it overrides the entire style of an element. Some options I have looked into:
DocumentStyle
Documents have a DocumentStyle property, but it does not contain any font information.
NamedStyles
Documents also have a NamedStyles property. It contains styles like NORMAL_TEXT and HEADING_1. I could loop through all these and change their textStyle.weightedFontFamily. This would be the ideal solution, because it would keep style information where it belongs. But I have not found a way to change NamedStyles using the API.
Deeper loop
I could continue with my current approach, looping through the elements list on each element, keeping everything but the font from textStyle (which contains things like bold: true). However, our current approach already takes too long to execute, and such an approach would be both slower and more brittle, so I would like to avoid this.
Answer:
Extract the textStyle out of the current element and only change/add the weightedFontFamily/fontFamily object.
Code Example:
for element in document["body"]["content"]:
if "sectionBreak" in element:
continue # Trying to change the font of a section break causes an error
textStyle = element["paragraph"]["elements"][0]["textStyle"]
textStyle["weightedFontFamily"]["fontFamily"] = "[Font name]"
requests.append(
{
"updateTextStyle": {
"range": {
"startIndex": element["startIndex"],
"endIndex": element["endIndex"],
},
"textStyle": textStyle,
"fields": "weightedFontFamily",
}
}
)
doc_service.documents().batchUpdate(
documentId=self.copy_id, body={"requests": requests}
).execute()
This seems to work for me, even with section breaks in between, and at the end of the document. You might want to explore more corner cases..
This basically tries to mimic the SelectAll option
document = service.documents().get(documentId=doc_id).execute()
endIndex = sorted(document["body"]["content"], key=lambda x: x["endIndex"], reverse=True,)[0]["endIndex"]
service.documents().batchUpdate(
documentId=doc_id,
body={
"requests": {
"updateTextStyle": {
"range": {
"endIndex": endIndex,
"startIndex": 1,
},
"fields": "fontSize",
"textStyle": {"fontSize": {"magnitude": 100, "unit": "pt"}},
}
}
},
).execute()
Same should work for other fields too.
However, if you are going to just share a docx file to all the clients, you could keep a local copy of the PDF / DOCX and then modify those. It is fairly easy to work around the styles in DOCX (it is a bunch of xml files)
Use this to explore and update DOCX files OOXML Tools Chrome Extension
Similarly PDFs are key-values pairs stored as records. Check this: ReportLab

Handling complex object trees in QML's model-view-delegate system?

I'm using QML with PyQt, and these two communicate with Qt's signal/slot system. I have Python objects which I've serialized to a JSON format, for example a list of stores and items sold in them:
[
{
"store": "Walmart",
"items": [
{
"name": "banana",
"price": 0.95
},
...
]
},
{
"store": "Target",
"items": [...]
},
...
]
This is then forwarded to QML with a signal, and then I store the whole JSON structure into a single variable, let's call it stores:
// main.qml
Window {
id: app
property var stores: []
// Slot function that's connected to Python
function onStoresInitialized(stores) {
app.stores = stores;
}
}
Now I have a ListView like so:
ListView {
model: app.stores
delegate: Column {
Repeater {
model: modelData["items"]
Text {
text: modelData["name"] + " $" + modelData["price"]
}
}
}
}
While the example is greatly simplified, it all seems to work fine up to this point. The problem arises when I want to update a single item, say we get a signal from Python that a particular item's price was updated. Our QML slot would look something like this:
function updatePrice(storeName, itemName, newPrice) {
for (let store : app.stores) {
if (store["name"] === storeName) {
for (let item : store["items"]) {
if (item["name"] === itemName) {
item["price"] = newPrice;
return;
}
}
}
}
}
This properly updates the price in my "model", but it doesn't signal the view of this change. I believe using raw data as a model is not the correct approach, but what is? All the QML guides seem to use simple data examples such as a 1D list of items with ListModel and ListElements, but what to do when I have a deep object tree such as here?
My QML days are long over, but one way to deal with this is to wrap the whole JSON into a custom object graph made with PyQt exposing the individual properties as pyqtProperty. And then massage the JSON into this object tree. We do this with a C++-model generated from a model specification in Python. It's a long story why it is that way, but it allows us to send JSON over the wire.
There might be a way to do all this in QML itself using QML types, but my personal preference for model creation would be in Python.

Categories

Resources