cannot parse json to xml using xmltodict.unparse when converting json list - json

Trying to do this using xmltodict.unparse:
I have this structure in json:
"organisations": [
{"organisation": "org1"},
{"organisation": "org2"},
{"organisation": "org3"}
]
But comes out like this in xml:
<organisations><organisation>org1</organisation></organisations>
<organisations><organisation>org2</organisation></organisations>
<organisations><organisation>org2</organisation></organisations>
I wanted like this:
<organisations>
<organisation>org1</organisation>
<organisation>org2</organisation>
<organisation>org2</organisation>
</organisations>
Im using xmltodict.unparse
def dict_to_xml(d, pretty_print=False, indent=DEFAULT_INDENT, document_root="root"):
if len(d.keys()) != 1:
d = {
document_root: d
}
res = xmltodict.unparse(d, indent=indent, short_empty_elements=True)
if pretty_print:
res = pretty_print_xml(res).strip()
return res
Anyone know what to do without hacking xmltodict??
thanks

I don't much about XML, but I got curious about this question and noticed:
Lists that are specified under a key in a dictionary use the key as a tag for each item.
https://github.com/martinblech/xmltodict#roundtripping
My approach was to reverse engineer the result you're after:
expected = '''
<organisations>
<organisation>org1</organisation>
<organisation>org2</organisation>
<organisation>org2</organisation>
</organisations>
'''
print(json.dumps(xmltodict.parse(expected), indent=4))
output:
{
"organisations": {
"organisation": [
"org1",
"org2",
"org2"
]
}
}
And "round tripping" that, gives the result you're after:
reverse = {
"organisations": {
"organisation": [
"org1",
"org2",
"org2"
]
}
}
print(xmltodict.unparse(reverse, pretty=True))
output:
<?xml version="1.0" encoding="utf-8"?>
<organisations>
<organisation>org1</organisation>
<organisation>org2</organisation>
<organisation>org2</organisation>
</organisations>
HTH!

Related

Modifying a json structure file with ruby

I tried with map and flat.map to restructure a json file (here is a sample it), with ruby from:
a= {
"_nb": {
"$nb": "55dd0"
},
"conf": "linux"
}
to
{
"_nb": "55dd0",
"conf": "linux"
}
or
{
"$nb": "55dd0",
"conf": "linux"
}
Could anyone point me in the right direction, please?
NOTE:
So far I add this solution implemented which returns a NoMethodError.. Hope this will help you both user1934428 & Cary Swoveland
..
File.open("src.json", "w") do |f|
hash_data = JSON.parse(File.read(a))
hash = hash_data.to_s
hash.each do |key, value|
if key == "_id"
hash[value] = value.values.first
end
end
f.puts(hash)
end
A first step might be:
hash = {
"_nb": {
"$nb": "55dd0"
},
"conf": "linux"
}
hash.transform_values { |value| value.is_a?(Hash) ? value.values.first : value }
#=> {:_nb=>"55dd0", :conf=>"linux"}
Note: This only works when the nesting is not deeper than one level and when the nested array has only one key/value pair.

Pulling specific Parent/Child JSON data with Python

I'm having a difficult time figuring out how to pull specific information from a json file.
So far I have this:
# Import json library
import json
# Open json database file
with open('jsondatabase.json', 'r') as f:
data = json.load(f)
# assign variables from json data and convert to usable information
identifier = data['ID']
identifier = str(identifier)
name = data['name']
name = str(name)
# Collect data from user to compare with data in json file
print("Please enter your numerical identifier and name: ")
user_id = input("Numerical identifier: ")
user_name = input("Name: ")
if user_id == identifier and user_name == name:
print("Your inputs matched. Congrats.")
else:
print("Your inputs did not match our data. Please try again.")
And that works great for a simple JSON file like this:
{
"ID": "123",
"name": "Bobby"
}
But ideally I need to create a more complex JSON file and can't find deeper information on how to pull specific information from something like this:
{
"Parent": [
{
"Parent_1": [
{
"Name": "Bobby",
"ID": "123"
}
],
"Parent_2": [
{
"Name": "Linda",
"ID": "321"
}
]
}
]
}
Here is an example that you might be able to pick apart.
You could either:
Make a custom de-jsonify object_hook as shown below and do something with it. There is a good tutorial here.
Just gobble up the whole dictionary that you get without a custom de-jsonify and drill down into it and make a list or set of the results. (not shown)
Example:
import json
from collections import namedtuple
data = '''
{
"Parents":
[
{
"Name": "Bobby",
"ID": "123"
},
{
"Name": "Linda",
"ID": "321"
}
]
}
'''
Parent = namedtuple('Parent', ['name', 'id'])
def dejsonify(json_str: dict):
if json_str.get("Name"):
parent = Parent(json_str.get('Name'), int(json_str.get('ID')))
return parent
return json_str
res = json.loads(data, object_hook=dejsonify)
print(res)
# then we can do whatever... if you need lookups by name/id,
# we could put the result into a dictionary
all_parents = {(p.name, p.id) : p for p in res['Parents']}
lookup_from_input = ('Bobby', 123)
print(f'found match: {all_parents.get(lookup_from_input)}')
Result:
{'Parents': [Parent(name='Bobby', id=123), Parent(name='Linda', id=321)]}
found match: Parent(name='Bobby', id=123)

Change name of main row Rails in JSON

So i have a json:
{
"code": "Q0934X",
"name": "PIDBA",
"longlat": "POINT(23.0 33.0)",
"altitude": 33
}
And i want to change the column code to Identifier
The wished output is this
{
"Identifier": "Q0934X",
"name": "PIDBA",
"longlat": "POINT(23.0 33.0)",
"altitude": 33
}
How can i do in the shortest way? Thanks
It appears that both "the json" you have and your desired result are JSON strings. If the one you have is json_str you can write:
json = JSON.parse(json_str).tap { |h| h["Identifier"] = h.delete("code") }.to_json
puts json
#=> {"name":"PIDBA","longlat":"POINT(23.0 33.0)","altitude":33,"Identifier":"Q0934X"}
Note that Hash#delete returns the value of the key being removed.
Perhaps transform_keys is an option.
The following seems to work for me (ruby 2.6):
json = JSON.parse(json_str).transform_keys { |k| k === 'code' ? 'Identifier' : k }.to_json
But this may work for Ruby 3.0 onwards (if I've understood the docs):
json = JSON.parse(json_str).transform_keys({ 'code': 'Identifier' }).to_json

Seeding rails project with Json file

I'm at a lost and my searches have gotten me nowhere.
In my seeds.rb file I have the following code
require 'json'
jsonfile = File.open 'db/search_result2.json'
jsondata = JSON.load jsonfile
#jsondata = JSON.parse(jsonfile)
jsondata[].each do |data|
Jobpost.create!(post: data['title'],
link: data['link'],
image: data['pagemap']['cse_image']['src'] )
end
Snippet of the json file looks like this:
{
"kind": "customsearch#result",
"title": "Careers Open Positions - Databricks",
"link": "https://databricks.com/company/careers/open-positions",
"pagemap": {
"cse_image": [
{
"src": "https://databricks.com/wp-content/uploads/2020/08/careeers-new-og-image-sept20.jpg"
}
]
}
},
Fixed jsondata[].each to jasondata.each. Now I'm getting the following error:
TypeError: no implicit conversion of String into Integer
jsondata[] says to call the [] method with no arguments on the object in the jsondata variable. Normally [] would take an index like jsondata[0] to get the first element or a start and length like jsondata[0, 5] to get the first five elements.
You want to call the each method on jsondata, so jsondata.each.
So this is very specific to what you have posted:
require 'json'
file = File.open('path_to_file.json').read
json_data = JSON.parse file
p json_data['kind'] #=> "customsearch#result"
# etc for all the other keys
now maybe the json you posted is just the first element in an array:
[
{}, // where each {} is the json you posted
{},
{},
// etc
]
in which case you will indeed have to iterate:
require 'json'
file = File.open('path_to_file.json').read
json_data = JSON.parse file
json_data.each do |data|
p data['kind'] #=> "customsearch#result"
end

Replace piece of json

I have a big .json file with geodata. Its a piece of this file. It has a repeating structure.
I want to save info about "id" and "area_value" and remove or replace other data.
With this structure.
{'Number':['id'],'Area sq.m.': ['area_value'],'Forest cov':'None','Status':'None'}
What method can be optimal for solving this problem?
Thanks!
{
"type":"FeatureCollection",
"crs":{
"type":"name",
"properties":{
"name":"EPSG:4326"
}
},
"features":[
{
"type":"Feature",
"properties":{
"date_create":"15.03.2008",
"statecd":"06",
"cc_date_approval":null,
"children":null,
"adate":"23.08.2017",
"cc_date_entering":"01.01.2014",
"rifr_cnt":null,
"parcel_build_attrs":null,
"rifr":null,
"sale_date":null,
"area_unit":"055",
"util_code":null,
"util_by_doc":null,
"area_value":115558.0,
"application_date":null,
"sale":null,
"cad_unit":"383",
"kvartal":"69:3:11",
"parent_id":"69:3:11:248",
"sale_cnt":null,
"sale_doc_date":null,
"date_cost":null,
"category_type":"003008000000",
"rifr_dep":null,
"kvartal_cn":"69:03:0000011",
"parent_cn":"69:03:0000011:248",
"cn":"69:03:0000011:245",
"is_big":false,
"rifr_dep_info":null,
"sale_dep":null,
"sale_dep_uo":null,
"parcel_build":false,
"id":"69:3:11:245",
"address":"\u0422\u0432\u0435\u0440\u0441\u043a\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0440-\u043d. \u0411\u0435\u043b\u044c\u0441\u043a\u0438\u0439, \u0441/\u043f. \u0415\u0433\u043e\u0440\u044c\u0435\u0432\u0441\u043a\u043e\u0435, \u0434. \u041e\u0441\u0438\u043f\u043e\u0432\u043e",
"area_type":"009",
"parcel_type":"parcel",
"sale_doc_num":null,
"sale_doc_type":null,
"sale_price":null,
"cad_cost":139698.06,
"fp":null,
"center":{
"x":33.14727379331379,
"y":55.87764081906541
}
}
}
You can try along the following lines:
import json
# some JSON:
x = '{ "name":"John", "age":30, "city":"New York"}'
# parse x:
y = json.loads(x)
# the result is a Python dictionary:
print(y["age"])