Hi,

I am currently getting JSON data from the discogs API (mp3 tag data) and wish to sort the results by the key's value. In this case I am trying to get data for a Guns n Roses song and the output has 1988 as the first one while the data actually has a record from 1987. How can I sort this data so that I can get to the sorted data by year (olderst to newest). The code below sorts by either key or value but thats not what I intended to get. Please help.

import json
import urllib2
request = urllib2.Request('http://api.discogs.com/database/search?sort=year&sort_order=asc&artist=%22Guns+N%27+Roses%22&track=%22Sweet+Child+O%27+Mine%22&format_exact=Album&type=master')
request.add_header('User-Agent','Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
request.add_header('Content-Type','application/json')
response = urllib2.urlopen(request)
json_raw= response.readlines()
json_object = json.loads(json_raw[0])



for row in json_object['results']:
    try:
        from operator import itemgetter
        for k, v in sorted(row.items(), key=itemgetter(0)):
            print k, v
    except KeyError: 
        pass

Dani AI

Generated

You are currently sorting the keys/values inside each result dictionary, not the list of result dictionaries itself. The Discogs response has a top-level list under results; that is what you need to sort. Also, avoid readlines()[0]; the response is a single JSON document, so load the whole body. Note that API-side sorting applies per page; if you want a truly global oldest-to-newest sort you should collect all pages, then sort client-side. The year field may be missing or a string, so coerce safely and push missing years to the end.

Example approach (Py2 urllib2), focusing on sorting the list:

import json, urllib2

req = urllib2.Request(url)
req.add_header('User-Agent', 'Mozilla/5.0')
req.add_header('Accept', 'application/json')
with urllib2.urlopen(req) as resp:
    data = json.load(resp)  # load entire JSON document

def year_key(r):
    try:
        return int(r.get('year'))
    except (TypeError, ValueError):
        return 10**9  # place items without a valid year at the end

sorted_results = sorted(
    data['results'],
    key=lambda r: (year_key(r), r.get('title', ''))
)
# iterate sorted_results as needed

If you need newest first, pass reverse=True. For multi-page results, iterate using the pagination info, extend a list with all pages, then sort once. See Python’s sorting guide for key functions and stability in tuples at Sorting HOWTO and JSON parsing details at json library. Discogs API pagination and sorting behavior are documented at Discogs Developers.

Recommended Answers

All 3 Replies

Why you do readlines as you only use first one?

This could help:

'''sort_dictionary_list1.py
sort a list of dictionaries by a value with a helper function
'''

import pprint

def sort_by_age(d):
    '''a helper function for sorting'''
    return d['age']

d_list = [
{
'name' : 'frank',
'age' : 24,
},
{
'name' : 'joe',
'age' : 21,
},
{
'name' : 'tim',
'age' : 18,
}]

pprint.pprint(d_list)
print('-'*30)
pprint.pprint(sorted(d_list, key=sort_by_age))

'''result -->
[{'age': 24, 'name': 'frank'},
 {'age': 21, 'name': 'joe'},
 {'age': 18, 'name': 'tim'}]
------------------------------
[{'age': 18, 'name': 'tim'},
 {'age': 21, 'name': 'joe'},
 {'age': 24, 'name': 'frank'}]
'''

Applied to your code:

'''json_read_url1.py
read json type data from a url and process it
tested with Python27
'''

import json
import urllib2

def sort_by_year(d):
    '''
    helper function for sorting a list of dictionaries'''
    return d.get('year', None)


# this is a long url so do it in parts
url1 = "http://api.discogs.com/database/search?sort=year&sort_order="
url2 = "asc&artist=%22Guns+N%27+Roses%22&track="
url3 = "%22Sweet+Child+O%27+Mine%22&format_exact=Album&type=master"
url = url1 + url2 + url3

request = urllib2.Request(url)

request.add_header('User-Agent','Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
request.add_header('Content-Type','application/json')

response = urllib2.urlopen(request)
json_raw = response.readlines()
json_object = json.loads(json_raw[0])

print(type(json_object['results']))  # test
print('-'*50)

for row in sorted(json_object['results'], key=sort_by_year):
    #print(row)
    try:
        print("%s = %s" % (row['title'], row['year']))  # test
    except:
        pass

'''my result -->
<type 'list'>
--------------------------------------------------
Guns N' Roses - Appetite For Destruction = 1987
Guns N' Roses - Sweet Child O' Mine = 1988
Guns N' Roses - November Rain = 1991
Guns N' Roses - Silent Shots = 1991
Guns N' Roses - Live Vol. 1 = 1993
Guns N' Roses - November Rain (Vol. 2) = 1993
Guns N' Roses - Banzai = 1993
Guns N' Roses - Welcome To The Videos = 1998
Guns N' Roses - Live Era '87-'93 = 1999
Guns N' Roses - Greatest Hits = 2004
'''
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.