0

I use the following code to sort key/value pairs in JSON files and append them in one file. This works if all keys are in the top level.

from collections import OrderedDict
from textwrap import indent
import json

for i in range(10):
    try:
        filename = str(i+1)+".json"
        def ordered(d, key_order):
            return OrderedDict([(key, d[key]) for key in key_order])

        desired_key_order = ("name", "description", "image", "attributes")
        with open(filename) as file:
            d = json.load(file)

        result = ordered(d, desired_key_order)
        print(json.dumps(result, indent=4))

        f = open("collection.json", "a")
        f.write(json.dumps(result, indent=4)+","+"\n")
        f.close()

    except Exception as e:
        print('NFT #'+str(i+1), ' is missing from the collection.', "\n")

I want to be able to do the same for files where one of the keys I want to sort among the top level ones is at second level.

I found this solution that I would like to use, but I wasn’t able to integrate it. I get a KeyError on 'edition'.

from collections import OrderedDict
from textwrap import indent
import json

for i in range(10):
    filename = str(i+1)+".json"
    with open(filename) as file:
        d = json.load(file)

    new_d = {key: d[key] for key in d}
    new_d.update(d['edition'])

    def ordered(new_d, key_order):
        return OrderedDict([(key, new_d[key]) for key in key_order])

    desired_key_order = ("edition", "name", "description", "image", "attributes")
    result = ordered(new_d, desired_key_order)
    print(json.dumps(result, indent=4))

    f = open("collection.json", "a")
    f.write(json.dumps(result, indent=4)+","+"\n")
    f.close()

script and sample data: https://github.com/BarryDB83/pythonscript

  • Please provide a [mre] of the problem along with sample data. – martineau Jun 29 '22 at 21:44
  • Rewrote the question and added a link to a Github repo with the script and sample data – P. Campbell Jun 29 '22 at 22:22
  • As an aside, **please don't wrap a bunch of code in an `try-except Exception` block. That is only going to mask a bunch of potential errors. Your `try-except` should wrap the minimal amount of code possible, and catch the most specific error possible. – juanpa.arrivillaga Jun 29 '22 at 22:30
  • 1
    What's the point of `new_d = {key: d[key] for key in d}`?? – juanpa.arrivillaga Jun 29 '22 at 22:31
  • 1
    Your question boils down to sorting the contents of a single JSON object, not reading a bunch of JSON files first to create it. So a minimal reproducible example would not have all that part in it and instead show the collected data before and after sorting (and your attempt to sort it). – martineau Jun 29 '22 at 22:32
  • Also note, if you are using a version of Python >= 3.6, there is no need for an `OrderedDict`, since plain `dict` objects maintain insertion order now. – juanpa.arrivillaga Jun 29 '22 at 22:32
  • What you are doing here, `f.write(json.dumps(result, indent=4)+","+"\n")` really doesn't make sense. Now the file, `collection.json` **isn't a valid JSON**. It isn't even a valid newline delimited JSON. – juanpa.arrivillaga Jun 29 '22 at 22:33
  • @juanpa.arrivillaga new_d = {key: d[key] for key in d} is how they solved it in the example I linked to. In that example they create a new dictionary first and update it with the second level key. As you can probably tell I am very new to this. The first piece of code does work for me and I can use the results as intented (upload it to a NFT ranking site that follows opensea standards) – P. Campbell Jun 29 '22 at 22:58
  • 1
    @P.Campbell in that link (you link to a question, not an answer, so I can only assume) they use `{key: d[key] for key in d if key != '_source'}` which actually does filtering based on the key. `{key: d[key] for key in d}` is completely pointless, there is no need to copy the dictionary, and if there was, you'd just do `new_d = d.copy()` or `new_d = dict(d)` – juanpa.arrivillaga Jun 29 '22 at 23:00
  • @juanpa.arrivillaga I adjusted the link to the answer, which is right below the question as you know very well. I am not trying to break the rules on purpose. It's okay though, I'll find a forum that's newbie friendly and tries to make one understand things instead of making them jump thru hoops. – P. Campbell Jun 29 '22 at 23:14
  • No one is saying you broke the rules, I'm saying, there are *multiple answers* in the link, I don't know which one you are using necessarily, I'm *just guessing* since the exact code isn't anywhere in there. I'm *trying* to make you understand things. I'm explaining to you what the code you are writing does, and how it should be written if you want it to be more idiomatic/conventional – juanpa.arrivillaga Jun 29 '22 at 23:39
  • @P.Campbell *If* a forum like that existed, then you likely wouldn't get the answer you were looking for. In any case, pointing out when there is something stupid or pointless happening in the code, is not hostile at all. It is simply making an observation, nothing more and nothing less. Try not to take all things as personal, especially on a site such as this where code review is a given for any question. – rv.kvetch Jun 30 '22 at 00:05
  • @rv.kvetch Are you stating that you don't understand what I'm trying to achieve? I'd say it's perfectly clear to everyone who responded here. But instead of pointing me in the right direction, you chose not to. Again, no problem though. I'm sure there's places where they look past wrong terminology and provide help instead of nitpicking. This question is now closed. – P. Campbell Jun 30 '22 at 03:16

1 Answers1

0
import json
from collections import OrderedDict

for i in range(10000):

    filename = str(i)+".json"

    with open(filename) as json_file:
        json_decoded = json.load(json_file)

    edition = json_decoded['custom_fields']['edition']

    json_decoded.update({"edition":edition})

    with open(filename, 'w') as f:
        f.write(json.dumps(json_decoded, sort_keys=False, indent=4, separators=(',', ': ')))

    def ordered(d, key_order):
        
        return OrderedDict([(key, d[key]) for key in key_order])

    desired_key_order = ("edition", "name", "description", "image", "attributes")

    with open(filename) as json_file:
        d = json.load(json_file)

    result = ordered(d, desired_key_order)

    f = open("collection.json", "a")

    f.write(json.dumps(result, indent=4)+","+"\n")

    f.close()
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 02 '22 at 02:49