0

I have a file, and each line of the file is a json object. For example:

{name:value1,city:value2}
{name:value3,city:value4}
etc.

What I am trying to do is run a line-by-line search on the file. If the value is equal to the searched parameter, update the value of the 2nd key in the object.

So for example, if the searched value is value1, I want to update the value of city for that object to an argument.

Here is what I have so far:

//trying first with 'fixed' values, will change to arguments once figured out...
with open('jsonfile.json', "r+", encoding='utf-8') as file:
    for line in file:
        res = json.loads(line)
        test_name = res['name']
        test_city = res['city']
        if test_name == "1":
            res['city'] = "hello"
        json.dump(res, file)

The current code successfully identifies if the test_name matches the searched parameter, however instead of updating the value, it appends a new dictionary entry at the end of the file.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
tzvik15
  • 123
  • 1
  • 11
  • I should mention that while directly updating the value is preferrable (I think?), I am OK with just overwriting the line (=object) with a new object that has the updated value. An idea I had (but am hoping for a better answer) is for each line, in the file, regardless if I update it or not, I can push to a list, and then from that list write a new file/overwrite the entire existing file. This seems possible but not very efficient? – tzvik15 Feb 28 '22 at 18:20

2 Answers2

1

you can use fileinput. i wrote a code similar to your code. used json.dumps because print itsel change double qoute with single qoute

import fileinput
import json

with fileinput.input('jsonfile.json', inplace=True) as file:
    for line in file:
        res = json.loads(line)
        if res['name'] == '1':
            res['city'] = "hello"
        print('{}'.format(json.dumps(res)), end='\n')        
ali
  • 53
  • 1
  • 5
0

Note that your input file is an ndjson. See the specs here

A simple function can do what you want, and you can iterate over the JSONs in the NDJSON as shown below.

Also, note that the pprint is not needed, it's just for output formatting...

python code

import ndjson
from pprint import pprint


def find_and_change(inputData, findKey, findValue, replaceKey, replaceValue):
    if findKey in inputData and replaceKey in inputData:  # avoid keyerrors
        if inputData[findKey] == findValue:
            inputData[replaceKey] = replaceValue
    return inputData


with open("testdata.ndjson") as infile:
    testdata = ndjson.load(infile)


pprint(testdata, indent=4)
print("------------------------------------------------------------")

for item in testdata:
    item = find_and_change(item, "name", "value2", "city", "thiswaschanged")

pprint(testdata, indent=4)

with open("outputdata.ndjson", "w") as outfile:
    ndjson.dump(testdata, outfile)

testdata.ndjson

{"name":"value1","city":"city1"}
{"name":"value2","city":"city0"}
{"name":"value2","city":"city1"}
{"name":"value3","city":"city3"}
{"name":"value4","city":"city4"}

output

[   {'city': 'city1', 'name': 'value1'},
    {'city': 'city0', 'name': 'value2'},
    {'city': 'city1', 'name': 'value2'},
    {'city': 'city3', 'name': 'value3'},
    {'city': 'city4', 'name': 'value4'}]
------------------------------------------------------------
[   {'city': 'city1', 'name': 'value1'},
    {'city': 'thiswaschanged', 'name': 'value2'},
    {'city': 'thiswaschanged', 'name': 'value2'},
    {'city': 'city3', 'name': 'value3'},
    {'city': 'city4', 'name': 'value4'}]

resulting outputdata.ndjson

{"name": "value1", "city": "city1"}
{"name": "value2", "city": "thiswaschanged"}
{"name": "value2", "city": "thiswaschanged"}
{"name": "value3", "city": "city3"}
{"name": "value4", "city": "city4"}
Edo Akse
  • 4,051
  • 2
  • 10
  • 21