I have a JSON file that I'm trying to parse. My script has a few print statements to check if I'm parsing the various fields correctly. It appears to be that way for ids and ip_metadata[ip] within the for loop. However, when I print out the entire dictionary at the end, the ids list is always the last ones. Only ids has this problem, the other fields were stored correctly. I can't see why ids isn't stored correctly.
JSON file:
{
"count": 4,
"data": [
{
"ip": "1.2.3.4",
"cty": {
"country": "US",
"organization": "ABC"
},
"info": {
"p": [
{
"id": 123,
"grp": "A"
},
{
"id": 234,
"grp": "B"
},
{
"id": 345,
"grp": "C"
},
{
"id": 456,
"grp": "D"
}
]
}
},
{
"ip": "2.3.4.5",
"cty": {
"country": "US",
"organization": "ABC"
},
"info": {
"p": [
{
"id": 111,
"grp": "A"
},
{
"id": 222,
"grp": "B"
},
{
"id": 333,
"grp": "C"
},
{
"id": 444,
"grp": "D"
}
]
}
},
{
"ip": "1.2.3.1",
"cty": {
"country": "AU",
"organization": "ABC"
},
"info": {
"p": [
{
"id": 222,
"grp": "A"
},
{
"id": 333,
"grp": "B"
},
{
"id": 444,
"grp": "C"
}
]
}
},
{
"ip": "10.2.3.4",
"cty": {
"country": "US",
"organization": "DDD"
},
"info": {
"p": [
{
"id": 555,
"grp": "A"
},
{
"id": 666,
"grp": "B"
},
{
"id": 777,
"grp": "C"
},
{
"id": 888,
"grp": "D"
}
]
}
}
],
"status": "ok"
}
My python script is
import json
import glob
from collections import defaultdict
ip_metadata = defaultdict(list)
def main():
for json_file in glob.glob("test_input/test_json.json"):
with open(json_file, "r") as fin:
ids = []
json_data = json.load(fin)
if json_data["count"] > 0:
for data in json_data['data']:
ip = data['ip']
country = data['cty']['country']
organization = data['cty']['organization']
ids[:] = []
ids_2 = data['info']['p']
for idss in ids_2:
id = idss['id']
grp = idss['grp']
ids.append((id,grp))
print(ids)
ip_metadata[ip].append((country,organization,ids))
print(ip_metadata[ip])
print("=============================")
for k, v in ip_metadata.items():
print(k,v)
if __name__ == '__main__':
main()
The output is
[(123, 'A'), (234, 'B'), (345, 'C'), (456, 'D')]
[('US', 'ABC', [(123, 'A'), (234, 'B'), (345, 'C'), (456, 'D')])]
[(111, 'A'), (222, 'B'), (333, 'C'), (444, 'D')]
[('US', 'ABC', [(111, 'A'), (222, 'B'), (333, 'C'), (444, 'D')])]
[(222, 'A'), (333, 'B'), (444, 'C')]
[('AU', 'ABC', [(222, 'A'), (333, 'B'), (444, 'C')])]
[(555, 'A'), (666, 'B'), (777, 'C'), (888, 'D')]
[('US', 'DDD', [(555, 'A'), (666, 'B'), (777, 'C'), (888, 'D')])]
=============================
1.2.3.4 [('US', 'ABC', [(555, 'A'), (666, 'B'), (777, 'C'), (888, 'D')])]
2.3.4.5 [('US', 'ABC', [(555, 'A'), (666, 'B'), (777, 'C'), (888, 'D')])]
1.2.3.1 [('AU', 'ABC', [(555, 'A'), (666, 'B'), (777, 'C'), (888, 'D')])]
10.2.3.4 [('US', 'DDD', [(555, 'A'), (666, 'B'), (777, 'C'), (888, 'D')])]
I managed to resolve this by removing the ids = [] line under the open() line, and replace ids[:] = [] with ids = [] instead. I don't quite understand why this fixes things, because I don't know why the value of ids would replace previously stored values of ids of different keys. But it works now.
Related
My current code:
create table Messages (
id int,
userId int,
message varchar(255)
);
insert into Messages
values
(1, 1, 'Message u1_1'),
(2, 1, 'Message u1_2'),
(3, 2, 'Message u2_1'),
(4, 2, 'Message u2_2'),
(5, 3, 'Message u3_1')
;
select
json_object('Messaging info',
json_object(
'id', userId,
'user', json_object(
'messages', json_arrayagg(
json_object(
'message', message,
'msgId', id
)
)
)
)
)
from Messages
where userId in (1, 2)
group by userId
This query returns 2 records that I cannot group into one json object.
In other words: i want to merge this
{"Messaging info": {"id": 1, "user": {"messages": [{"msgId": 1, "message": "Message u1_1"},{"msgId": 2, "message": "Message u1_2"}]}}}
and this
{"Messaging info": {"id": 2, "user": {"messages": [{"msgId": 3, "message": "Message u2_1"}, {"msgId": 4, "message": "Message u2_2"}]}}}
into
{
"Messaging info": {
"id": 1,
"user": {
"messages": [
{
"msgId": 1,
"message": "Message u1_1"
},
{
"msgId": 2,
"message": "Message u1_2"
}
]
},
"id": 2,
"user": {
"messages": [
{
"msgId": 3,
"message": "Message u2_1"
},
{
"msgId": 4,
"message": "Message u2_2"
}
]
}
}
}
Tried to play with json_arrayagg at topmost of query, but got a grouping error.
https://www.db-fiddle.com/f/rjmkqmM5AvvPDAXbzrTBNY/1
Thanks in advance.
You need to do json_arrayagg in the outer query
SELECT json_object('Messaging info',json_arrayagg(ad))
FROM(
select
json_object(
'id', userId,
'user', json_object(
'messages', json_arrayagg(
json_object(
'message', message,
'msgId', id
)
)
)
) as ad
from Messages
https://www.db-fiddle.com/f/rjmkqmM5AvvPDAXbzrTBNY/2
I want to return the query result as a JSON object from the SQL server. I have below Employee and EmployeeDtl table.
DROP TABLE IF EXISTS #Employee
CREATE TABLE #Employee (EmpId bigint, EmpName varchar(2000))
INSERT INTO #Employee VALUES (1, 'A')
DROP TABLE IF EXISTS #EmployeeDtl
CREATE TABLE #EmployeeDtl (EmpId bigint, WorkObject varchar(100), LocationName varchar(100))
INSERT INTO #EmployeeDtl VALUES (1, 'AAA', 'AAAAA')
INSERT INTO #EmployeeDtl VALUES (1, 'BBB', 'BBBB')
INSERT INTO #EmployeeDtl VALUES (1, 'CCC', 'CCCC')
I want to return the data in the below format.
{
"Employees": [{
"EmpId": 1,
"EmpName": "A",
"EmpDtl": [{
"WorkObject": "AAA",
"LocationName": "AAAAA"
},
{
"WorkObject": "BBB",
"LocationName": "BBBB"
},
{
"WorkObject": "CCC",
"LocationName": "CCCC"
}
]
}]
}
I've written the below query.
SELECT
E.EmpId, E.EmpName, ED.WorkObject AS [EmpDtl.WorkObject], ED.LocationName AS [EmpDtl.LocationName]
FROM
#Employee E
INNER JOIN #EmployeeDtl ED ON E.EmpId = ED.EmpId
FOR
JSON PATH, ROOT('Employees')
But, the above query is returning data in the below format.
{
"Employees": [{
"EmpId": 1,
"EmpName": "A",
"EmpDtl": {
"WorkObject": "AAA",
"LocationName": "AAAAA"
}
}, {
"EmpId": 1,
"EmpName": "A",
"EmpDtl": {
"WorkObject": "BBB",
"LocationName": "BBBB"
}
}, {
"EmpId": 1,
"EmpName": "A",
"EmpDtl": {
"WorkObject": "CCC",
"LocationName": "CCCC"
}
}]
}
Can you please help me to understand what I'm doing wrong here.
You need to nest #EmployeeDtl as a subquery instead:
SELECT E.EmpId,
E.EmpName,
(SELECT ED.WorkObject AS [WorkObject],
ED.LocationName AS [LocationName]
FROM #EmployeeDtl ED
WHERE ED.EmpId = E.EmpId
FOR JSON PATH) AS EmpDtl
FROM #Employee E
FOR JSON PATH, ROOT('Employees');
Output:
{
"Employees": [
{
"EmpId": 1,
"EmpName": "A",
"EmpDtl": [
{
"WorkObject": "AAA",
"LocationName": "AAAAA"
},
{
"WorkObject": "BBB",
"LocationName": "BBBB"
},
{
"WorkObject": "CCC",
"LocationName": "CCCC"
}
]
}
]
}
Sorry for the basic of this question, I just cannot wrap my head around this one.
I need the output from SQL Server to look like this.
In a little more human readable format:
var data = [
{
name: '2017', id: -1,
children: [
{ name: '01-2017', id: 11 },
{ name: '02-2017', id: 12 },
{ name: '03-2017', id: 13 },
{ name: '04-2017', id: 14 },
{ name: '05-2017', id: 15 },
]
},
{
name: '2018', id: -1,
children: [
{ name: '01-2018', id: 6 },
{ name: '02-2018', id: 7 },
{ name: '03-2018', id: 8 },
{ name: '04-2018', id: 9 },
{ name: '05-2018', id: 10 },
]
}
];
This is a snapshot of the data:
The group I will be working with is userid = 1.
My first thought was to use a cursor to loop through all the distinct reportYear for userid = 1, then a select based on the year and the userid to fill in the sub-query.
There has to be a way without using a cursor.
You can achieve the desired output joining your table to a query that extracts all the years to be used at the top level elements and then generating the json using FOR JSON AUTO:
declare #tmp table (monthlyReportID int, userID int, reportMonth int, reportYear int)
insert into #tmp values
( 6, 1, 1, 2018),
( 7, 1, 2, 2018),
( 8, 1, 3, 2018),
( 9, 1, 4, 2018),
(10, 1, 5, 2018),
(11, 1, 1, 2017),
(12, 1, 2, 2017),
(13, 1, 3, 2017),
(14, 1, 4, 2017),
(15, 1, 5, 2017)
select years.[name], children.[name], children.[id] from
(
select distinct reportYear as [name] from #tmp
) as years
left join
(
select monthlyReportID as [id]
,right('0' + cast(reportMonth as varchar(2)),2) + '-' + cast(reportYear as varchar(4)) as [name]
,reportYear as [year]
from #tmp
) as children
on children.[Year] = years.[name]
for json auto
I omitted the ID field because in your desired output it is always set to -1 and I was not able to understand the logic behind it.
Nonetheless you should be able to easily edit the script above to obtain the value you need.
Here are the results:
[
{
"name": 2017,
"children": [
{"name": "01-2017", "id": 11},
{"name": "02-2017", "id": 12},
{"name": "03-2017", "id": 13},
{"name": "04-2017", "id": 14},
{"name": "05-2017", "id": 15}
]
},
{
"name": 2018,
"children": [
{"name": "01-2018", "id": 6},
{"name": "02-2018", "id": 7},
{"name": "03-2018", "id": 8},
{"name": "04-2018", "id": 9},
{"name": "05-2018", "id": 10}
]
}
]
I'm trying to convert a .csv to json/dict such that the data in its current form:
cat1,cat2,cat3,name
1,2,3,a
4,5,6,b
7,8,9,c
I'm currently using something like this(as well as importing using pandas.df bc it will be used for graphing from json file):
with open('Data.csv') as f:
reader = csv.DictReader(f)
rows = list(reader)
print (rows)
[{'cat1': '1', 'name': 'a', 'cat3': '3', 'cat2': '2'},
{'cat1': '4', 'name': 'b', 'cat3': '6', 'cat2': '5'},
{'cat1': '7', 'name': 'c', 'cat3': '9', 'cat2': '8'}]
and I want it to look like this in json/dict format:
{"data: [{"all_cats": {"cat1": 1}, {"cat2": 2}, {"cat3": 3}}, "name": a},
{"all_cats": {"cat1": 4}, {"cat2": 5}, {"cat3": 6}}, "name": b},
{"all_cats": {"cat1": 7}, {"cat2": 8}, {"cat3": 8}}, "name": c}]}
Importing directly doesn't allow me to include: 'cat1', 'cat2', 'cat3' under 'all_cats' and keep 'name' separate.
Any help would be appreciated.
Since it's space separated and not comma separated you have to add delimiter=" ". Additionally since some of your rows have whitespace beforehand, that means you also have to add skipinitialspace=True.
reader = csv.DictReader(f, delimiter=" ", skipinitialspace=True)
rows = list(dict(row) for row in reader)
Thus if you now do:
for row in rows:
print(row)
The output will be:
{'cat1': '1', 'cat2': '2', 'cat3': '3', 'name': 'a'}
{'cat1': '4', 'cat2': '5', 'cat3': '6', 'name': 'b'}
{'cat1': '7', 'cat2': '8', 'cat3': '9', 'name': 'c'}
As already mentioned in the other answer you don't specify valid JSON format for what you want to achieve. You can check if a string contains valid JSON format using json.loads(jsonDATAstring) function:
import json
jsonDATAstring_1 = """
{"data: [{"all_cats": {"cat1": 1}, {"cat2": 2}, {"cat3": 3}}, "name": a},
{"all_cats": {"cat1": 4}, {"cat2": 5}, {"cat3": 6}}, "name": b},
{"all_cats": {"cat1": 7}, {"cat2": 8}, {"cat3": 8}}, "name": c}]}
"""
json.loads(jsonDATAstring_1)
what in case of the by you specified expected JSON format results in:
json.decoder.JSONDecodeError: Expecting ':' delimiter: line 2 column 12 (char 12)
From what is known to me from your question I assume, that the JSON string you want to get is a following one:
jsonDATAstring_2 = """
{"data": [{"all_cats": {"cat1": 1, "cat2": 2, "cat3": 3}, "name": "a"},
{"all_cats": {"cat1": 4, "cat2": 5, "cat3": 6}, "name": "b"},
{"all_cats": {"cat1": 7, "cat2": 8, "cat3": 8}, "name": "c"}]}
"""
json.loads(jsonDATAstring_2)
This second string loads OK, so assuming:
rows = [{'cat1': '1', 'name': 'a', 'cat3': '3', 'cat2': '2'},
{'cat1': '4', 'name': 'b', 'cat3': '6', 'cat2': '5'},
{'cat1': '7', 'name': 'c', 'cat3': '9', 'cat2': '8'}]
you can get what you want as follows:
dctData = {"data": []}
lstCats = ['cat1', 'cat2', 'cat3']
for row in rows:
dctAllCats = {"all_cats":{}, "name":"?"}
for cat in lstCats:
dctAllCats["all_cats"][cat] = row[cat]
dctAllCats["name"] = row["name"]
dctData["data"].append(dctAllCats)
import pprint
pp = pprint.PrettyPrinter()
pp.pprint(dctData)
what gives:
{'data': [{'all_cats': {'cat1': '1', 'cat2': '2', 'cat3': '3'}, 'name': 'a'},
{'all_cats': {'cat1': '4', 'cat2': '5', 'cat3': '6'}, 'name': 'b'},
{'all_cats': {'cat1': '7', 'cat2': '8', 'cat3': '9'}, 'name': 'c'}]}
Now it is possible to serialize the Python dictionary object to JSON string (or file):
jsonString = json.dumps(dctData)
print(jsonString)
what gives:
{"data": [{"all_cats": {"cat1": "1", "cat2": "2", "cat3": "3"}, "name": "a"}, {"all_cats": {"cat1": "4", "cat2": "5", "cat3": "6"}, "name": "b"}, {"all_cats": {"cat1": "7", "cat2": "8", "cat3": "9"}, "name": "c"}]}
I'm trying to achieve table structure attached in the image :
Composite Class Routine
So far what I've tried can be seen in the following Plunker:
https://plnkr.co/edit/4WiWKDIM2bNfnmRjFo91?p=preview
My json data is :
$scope.routines = [
{
"WEEKDAY_ID": 1,
"WEEKDAY": "Sunday",
"aSemester": [
{
"SEMESTER_ID": 1,
"SEMESTER_NAME": "1st",
"aClassTime": [
{
"COURSE_ID": 1,
"COURSE_CODE": "CSTE-1001",
"CLASS_DURATION": 3,
"CLASSTIME_ID": 1,
"CLASSTIME": "9.00-9.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-1",
"ROOM_NO": 101,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 10,
"INSTRUCTOR_NAME": "Abhijit Chakraborty",
"SHORT_CODE": "AC"
},
{
"COURSE_ID": 7,
"COURSE_CODE": "CSTE-1106",
"CLASS_DURATION": 1,
"CLASSTIME_ID": 4,
"CLASSTIME": "12.00-12.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-2",
"ROOM_NO": 258,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 10,
"INSTRUCTOR_NAME": "Abhijit Chakraborty",
"SHORT_CODE": "AC"
},
{
"COURSE_ID": 3,
"COURSE_CODE": "CSTE-1102",
"CLASS_DURATION": 1,
"CLASSTIME_ID": 7,
"CLASSTIME": "4.00-4.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-2",
"ROOM_NO": 252,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 9,
"INSTRUCTOR_NAME": "Dr. Md. Asadun Nabi",
"SHORT_CODE": "MAN"
}
]
},
{
"SEMESTER_ID": 2,
"SEMESTER_NAME": "2nd",
"aClassTime": [
{
"COURSE_ID": 7,
"COURSE_CODE": "CSTE-1106",
"CLASS_DURATION": 1,
"CLASSTIME_ID": 1,
"CLASSTIME": "9.00-9.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-4",
"ROOM_NO": 456,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 6,
"INSTRUCTOR_NAME": "Dr. Humayun Kabir",
"SHORT_CODE": "HK"
},
{
"COURSE_ID": 3,
"COURSE_CODE": "CSTE-1102",
"CLASS_DURATION": 1,
"CLASSTIME_ID": 2,
"CLASSTIME": "10.00-10.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-1",
"ROOM_NO": 102,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 6,
"INSTRUCTOR_NAME": "Dr. Humayun Kabir",
"SHORT_CODE": "HK"
}
]
},
{
"SEMESTER_ID": 3,
"SEMESTER_NAME": "3rd",
"aClassTime": [
{
"COURSE_ID": 5,
"COURSE_CODE": "CSTE-4202",
"CLASS_DURATION": 1,
"CLASSTIME_ID": 7,
"CLASSTIME": "4.00-4.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-2",
"ROOM_NO": 252,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 7,
"INSTRUCTOR_NAME": "Md. Javed Hossain",
"SHORT_CODE": "MJH"
}
]
},
{
"SEMESTER_ID": 4,
"SEMESTER_NAME": "4th",
"aClassTime": [
{
"COURSE_ID": 61,
"COURSE_CODE": "CSTE-2204",
"CLASS_DURATION": 2,
"CLASSTIME_ID": 1,
"CLASSTIME": "9.00-9.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-1",
"ROOM_NO": 404,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 6,
"INSTRUCTOR_NAME": "Dr. Humayun Kabir",
"SHORT_CODE": "HK"
},
{
"COURSE_ID": 62,
"COURSE_CODE": "CSTE-2206",
"CLASS_DURATION": 2,
"CLASSTIME_ID": 3,
"CLASSTIME": "11.00-11.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-1",
"ROOM_NO": 101,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 10,
"INSTRUCTOR_NAME": "Abhijit Chakraborty",
"SHORT_CODE": "AC"
},
{
"COURSE_ID": 63,
"COURSE_CODE": "CSTE-2202",
"CLASS_DURATION": 3,
"CLASSTIME_ID": 5,
"CLASSTIME": "2.00-2.50",
"DEPT_ID": 1,
"DEPT_NAME": "Computer Science",
"BUILDING_NAME": "Academic-3",
"ROOM_NO": 303,
"LAB_GROUP": null,
"INSTRUCTOR_ID": 7,
"INSTRUCTOR_NAME": "Md. Javed Hossain",
"SHORT_CODE": "MJH"
}
]
}
]
}
];
and html I tried so far is :
<table id="routines" class="table table-bordered table-responsive table-condensed">
<thead>
<tr>
<th>Day</th>
<th>Semester</th>
<th ng-repeat="c in classtimes">{{c.CLASSTIME}}</th>
</tr>
</thead>
<tbody ng-repeat="r in routines">
<tr ng-repeat="s in r.aSemester">
<td rowspan="{{r.aSemester.length}}">{{r.WEEKDAY}}</td>
<td>{{s.SEMESTER_NAME}}</td>
<td colspan={{c.CLASS_DURATION}}
ng-repeat="c in s.aClassTime">
{{c.COURSE_CODE}}
</td>
</tr>
</tbody>
any kind of help would be appreciated.
Replace your table body with this
<tbody>
<tr ng-repeat-start="r in routines">
<td rowspan="{{r.aSemester.length+1}}">{{r.WEEKDAY}}</td>
</tr>
<tr ng-repeat="aSem in r.aSemester">
<td>{{aSem.SEMESTER_NAME}}</td>
<td ng-repeat="c in classtimes">
<span ng-repeat="classTime in aSem.aClassTime">
<span ng-if="classTime.CLASSTIME_ID==c.CLASSTIME_ID">
{{classTime.COURSE_CODE}}
</span>
</span>
</td>
</tr>
<tr ng-repeat-end ></tr>
</tbody>
I think this should help.
Plunkr https://plnkr.co/edit/QFUouMmSKtBiAWMdGpCC?p=preview