1

a.json file:

{
  "a": "b",
  "key": "graph: \"color\" = 'black' AND \"api\" = 'demo-application-v1' nodes",
  "c": "d"
}

following code I tried:

string_to_be_replace = "abcd"
string_to = "graph: \"color\" = 'black' AND \"api\" = 'demo-application-v1' nodes"
string_to_be_identified = "\"color\" = \'black\' AND \"api\" = \'demo-application-v1\'"
string_to_be_identified1 = '"color" = \'black\' AND "api" = \'demo-application-v1\''

print string_to_be_identified
print string_to_be_identified1
print string_to.replace(string_to_be_identified1,string_to_be_replace)
print string.replace(string_to, string_to_be_identified,string_to_be_replace)

output:

"color" = 'black' AND "api" = 'demo-application-v1'
"color" = 'black' AND "api" = 'demo-application-v1'
graph: abcd nodes
graph: abcd nodes

This is working fine and replacing string as expected but

it is not when I tried the following approaches

Approach 1:

  1. Open file in a read mode,

  2. get line by line and replace string

with open(path + '/a.json', 'r') as file:
    read_lines = file.readlines()
    for line in read_lines:
        print line.replace(string_to_be_identified,string_to_be_replace)
file.close()

output:

{
  "a": "b",
  "key": "graph: \"color\" = 'black' AND \"api\" ='demo-application-v1' node",
  "c": "d"
}

Approach 2:

  1. Open file in reading mode,

  2. Since the file a.json has JSON data, get JSON file loaded, convert JSON object to JSON-string and then replace it.

Code:

 with open(path + '/a.json', 'r') as file:
    loadedJson = json.load(file)
    print "z: " + str(loadedJson).replace(string_to_be_identified, string_to_be_replace)
file.close()

output:

z: {u'a': u'b', u'c': u'd', u'key': u'graph: "color" = 'black' AND "api" = 'demo-application-v1' node'}

Approach 3:

I assume Unicode character in JSON string might be creating a problem so converted Unicode string to normal string and then tried to replace string

code:

def byteify(input):
    if isinstance(input, dict):
        return {byteify(key): byteify(value)
                for key, value in input.iteritems()}
    elif isinstance(input, list):
        return [byteify(element) for element in input]
    elif isinstance(input, unicode):
        return input.encode('utf-8')
    else:
        return input

with open(path + '/a.json', 'r') as file:
    loadedJson = json.load(file)
    js = byteify(loadedJson)
    print "a: " + str(js).replace(string_to_be_identified, string_to_be_replace)

output:

a: {'a': 'b', 'c': 'd', 'key': 'graph: "color" = 'black' AND "api" = 'demo-application-v1' node'}

  • python version:2.7.15
  • using byteify code from one of the SO answer.
  • JSON file is big and cannot do the manual search and replace.
  • There is no difference in ' and " in python still tried in above example.
dkb
  • 4,389
  • 4
  • 36
  • 54
  • Any particular reason why are you trying to do plain search & replace on hierarchical data such as JSON? Why don't you parse the JSON, replace what you need properly, and then serialize it to JSON again? – zwer Sep 20 '18 at 12:19
  • @zwer, Json is too big to go to the particular hierarchies, and the worst part is, String is a field in a complex object which intern present in an array of non-uniform complex objects. Now this string might be present as part of another object in future and if it is not present in parsing logic then we might miss it, so thought of string replace solution, which will work irrespective of depth of field in json. – dkb Sep 20 '18 at 12:24

1 Answers1

1

While I certainly do not recommend any sort of context-unaware search & replace in a hierarchical structure like JSON, your main issue is that the string you're searching for in your JSON file has escaped quotations (literal \ characters) so you have to account for those as well if you want to do plain text search. You can use either raw strings or add the backslashes yourself, something like:

str_search = r"graph: \"color\" = 'black' AND \"api\" = 'demo-application-v1'"
# or, if you prefer to manually write down the string instead of declaring it 'raw':
# str_search = "graph: \\\"color\\\" = 'black' AND \\\"api\\\" = 'demo-application-v1'"
str_replace = "abcd"

with open("/path/to/your.json", "r") as f:
    for line in f:
        print(line.replace(str_search, str_replace))

Which, for your JSON, will yield:

{

  "a": "b",

  "key": "abcd nodes",

  "c": "d"

}

(Extra new lines added by print).

zwer
  • 24,943
  • 3
  • 48
  • 66
  • I did not know about raw string, Thank you! @Zwer, this helped :) – dkb Sep 20 '18 at 13:15
  • some more info on raw string:https://stackoverflow.com/questions/2081640/what-exactly-do-u-and-r-string-flags-do-and-what-are-raw-string-literals – dkb Sep 20 '18 at 13:20
  • Some more info: Raw string operation is different from usual string concatenation, color is user defind variable: e.g. `r"AND color = '" + color + "' AND \"api\"` then better you should be doing `r"AND color = '" + color + r"' AND \"api\"` – dkb Sep 27 '18 at 09:57