www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A trick to control the key ordering of JSONValue.toString

reply timepp <tongjunhui live.cn> writes:
As documented, when you output a JSONValue to string, keys are 
always in ascent order. In some case the output will be consumed 
by human so a specific key order is important.

This really caused my headache for some time. When I was about to 
rewrite my own toString method I found a quick, dirty but clever 
idea as below.

string toPrettyStringWithOrder(JSONValue j, string[] keys) {
	auto str = j.toString();
	for (int i = 0; i < keys.length; i++) {
		string oldkey = keys[i];
		string newkey = format("__%02d__", i) ~ oldkey;
		str = str.replace("\"" ~ oldkey ~ "\":", "\"" ~ newkey ~ "\":");
	}
	JSONValue jj = parseJSON(str);
	str = jj.toPrettyString();
	
	auto re = regex(r"__[0-9][0-9]__","g");
	return replaceAll(str, re, "");
}

my usage:
f.write(toPrettyStringWithOrder(j, ["name", "group", "type", 
"talent", "skill", "source", "tag", "gallary"]));

It lacks of preciseness. But it's enough to me. Hope this help 
you as well.
Jan 03
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 4 January 2019 at 07:38:39 UTC, timepp wrote:
 As documented, when you output a JSONValue to string, keys are 
 always in ascent order. In some case the output will be 
 consumed by human so a specific key order is important.

 This really caused my headache for some time. When I was about 
 to rewrite my own toString method I found a quick, dirty but 
 clever idea as below.

 string toPrettyStringWithOrder(JSONValue j, string[] keys) {
 	auto str = j.toString();
 	for (int i = 0; i < keys.length; i++) {
 		string oldkey = keys[i];
 		string newkey = format("__%02d__", i) ~ oldkey;
 		str = str.replace("\"" ~ oldkey ~ "\":", "\"" ~ newkey ~ 
 "\":");
 	}
 	JSONValue jj = parseJSON(str);
 	str = jj.toPrettyString();
 	
 	auto re = regex(r"__[0-9][0-9]__","g");
 	return replaceAll(str, re, "");
 }

 my usage:
 f.write(toPrettyStringWithOrder(j, ["name", "group", "type", 
 "talent", "skill", "source", "tag", "gallary"]));

 It lacks of preciseness. But it's enough to me. Hope this help 
 you as well.
About a year ago I had the same problem. I was able to extend std.json with a "policy" that allowed an application to specify custom types for json objects. Then in my application I just defined my own object type that preserved the field order that the json object was parsed from. I created a Pull Request in phobos for std.json to allow applications to specify a policy to customize json behavior (https://github.com/dlang/phobos/pull/6059), however, Andrei rejected the phobos PR saying that preserving field order was an "anitpatern" in JSON (even though the phobos PR was just adding a Policy interface, nothing to do with preserving field order) and also saying that std.json is disliked so adding features doesn't make any sense. Andrei tends to skim over pull requests without understanding them and its impossible to maintain a conversation with him to explain so I just closed the pull request so I didn't have to deal with it. In the end, to preserve field order I just implemented my own simple JSON parser in 400 lines of D code: https://github.com/marler8997/stupidjsonparser
Jan 04