SQL Server 2016 introduced some JSON features, but they're far from robust. As far as I can tell, there's no way yet to output a simple array; everything must be in "key": "value"
format. I don't want to do what some answers propose and write a partial JSON encoder within SQL.
Therefore, I'm stripping out certain keys in the Python side of my program.
SQL statement (I'd tag this with PowerCampus, the ERP product, if the tag existed):
SELECT SECTIONS.EVENT_ID
,SECTIONS.EVENT_LONG_NAME
,SECTIONS.ACADEMIC_YEAR
,SECTIONS.ACADEMIC_TERM
,SECTIONS.ACADEMIC_SESSION
,SECTIONS.EVENT_SUB_TYPE
,SECTIONS.SECTION
,TRANSCRIPTDETAIL.PEOPLE_CODE_ID
FROM [SECTIONS]
INNER JOIN [TRANSCRIPTDETAIL]
ON TRANSCRIPTDETAIL.EVENT_ID = SECTIONS.EVENT_ID
AND TRANSCRIPTDETAIL.ACADEMIC_YEAR = SECTIONS.ACADEMIC_YEAR
AND TRANSCRIPTDETAIL.ACADEMIC_TERM = SECTIONS.ACADEMIC_TERM
AND TRANSCRIPTDETAIL.ACADEMIC_SESSION = SECTIONS.ACADEMIC_SESSION
AND TRANSCRIPTDETAIL.EVENT_SUB_TYPE = SECTIONS.EVENT_SUB_TYPE
AND TRANSCRIPTDETAIL.SECTION = SECTIONS.SECTION
AND TRANSCRIPTDETAIL.ADD_DROP_WAIT = 'A'
WHERE SECTIONS.ACADEMIC_YEAR = '2019'
AND SECTIONS.ACADEMIC_TERM = 'SPRING'
FOR JSON AUTO
JSON output:
[
{
"SectionId": "ENG101",
"LongName": "English 102",
"AcademicYear": "2019",
"AcademicTerm": "SPRING",
"AcademicSession": "01",
"SubType": "LEC",
"Section": "ABC",
"Students": [
{
"PeopleCodeId": "P000111602"
},
{
"PeopleCodeId": "P000109552"
},
{
"PeopleCodeId": "P000110652"
},
{
"PeopleCodeId": "P000111872"
},
{
"PeopleCodeId": "P000111772"
},
{
"PeopleCodeId": "P000111802"
},
{
"PeopleCodeId": "P000111792"
},
{
"PeopleCodeId": "P000111722"
},
{
"PeopleCodeId": "P000111802"
},
{
"PeopleCodeId": "P000111442"
}
]
},
{
"EVENT_ID": "ENG101",
"EVENT_LONG_NAME": "English 102",
"ACADEMIC_YEAR": "2019",
"ACADEMIC_TERM": "SPRING",
"ACADEMIC_SESSION": "01",
"EVENT_SUB_TYPE": "LEC",
"SECTION": "ABC",
"TRANSCRIPTDETAIL": [
{
"PEOPLE_CODE_ID": "P000112582"
},
{
"PEOPLE_CODE_ID": "P000113022"
},
{
"PEOPLE_CODE_ID": "P000113062"
},
{
"PEOPLE_CODE_ID": "P000112152"
},
{
"PEOPLE_CODE_ID": "P000112212"
},
{
"PEOPLE_CODE_ID": "P000112812"
},
{
"PEOPLE_CODE_ID": "P000112662"
},
{
"PEOPLE_CODE_ID": "P000112072"
},
{
"PEOPLE_CODE_ID": "P000112222"
},
{
"PEOPLE_CODE_ID": "P000112442"
}
]
}
]
My Python function correctly collapses the PEOPLE_CODE_ID's into a simple array:
[
{
"SectionId": "ENG101",
"LongName": "English 102",
"AcademicYear": "2019",
"AcademicTerm": "SPRING",
"AcademicSession": "01",
"SubType": "LEC",
"Section": "ABC",
"Students": [
"P000111602",
"P000109552",
"P000110652",
"P000111872",
"P000111772",
"P000111802",
"P000111792",
"P000111722",
"P000111802",
"P000111442"
]
},
{
"EVENT_ID": "ENG101",
"EVENT_LONG_NAME": "English 102",
"ACADEMIC_YEAR": "2019",
"ACADEMIC_TERM": "SPRING",
"ACADEMIC_SESSION": "01",
"EVENT_SUB_TYPE": "LEC",
"SECTION": "ABC",
"TRANSCRIPTDETAIL": [
"P000112582",
"P000113022",
"P000113062",
"P000112152",
"P000112212",
"P000112812",
"P000112662",
"P000112072",
"P000112222",
"P000112442"
]
}
]
Here's the function:
def clean_sql_json(x):
"""Cleans up JSON produced by SQL Server by reducing this pattern:
[{"Key": [{"Key": "Value"}]}]
to this:
[{'Key': ['Value']}]
Also removes duplicates (and ordering) from the reduced list.
"""
data = json.loads(x)
for k in data:
for kk, vv in k.items():
if type(vv) == list and type(vv[0] == dict) and len(vv[0]) == 1:
newlist = [kkk[list(vv[0].keys())[0]] for kkk in vv]
data[data.index(k)][kk] = list(set(newlist))
return data
I'm a little concerned about the Python. Is it safe to modify and return data
on the fly like this?