Reputation: 199
suppose I have a long listed JSON
file which holds bunch of information. I was making a rest call to make an update request of an API
which is implemented using Spring
and Hibernate framework
.
The problem I faced is on each repetitive calls that I make to validate my update operation, I have to go through all the JSON
file and bump up the 'version' number attribute of any involving object, so that Hibernate will not complain about the coming data. However, doing this always is time consuming and really tiresome. What can i use to update the version number in my JSON
programmatically or I can use online tool if there is any so that i can save time on my repetitive rest call.
Thank you
Upvotes: 2
Views: 213
Reputation: 1649
Here is how I would solve this problem if I needed fast low level pure Java solution working in JSON token stream way provided by FastXML/Jackson library:
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class JsonTokenStreamTest {
public static void main(String[] args) throws IOException {
String inputJson = "[{},{\"k1\":null,\"k2\":true,\"k3\":\"v3\",\"k/4\":[123, 45],\"k~5\":6.7}]";
Reader r = new StringReader(inputJson);
StringWriter w = new StringWriter();
substitute(r, "/1/k~14/0", 124, w); // "~1" in json-pathes means "/"
String outputJson = w.toString();
System.out.println(outputJson);
}
public static void substitute(Reader r, String path, Object value,
Writer w) throws IOException {
if (path.length() > 0 && !path.startsWith("/"))
path = "/" + path;
if (path.endsWith("/"))
path = path.substring(0, path.length() - 1);
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createParser(r);
JsonGenerator jGenerator = jfactory.createGenerator(w);
StringBuilder curTextPath = new StringBuilder();
List<Object> curObjPath = new ArrayList<Object>();
while (true) {
JsonToken jt = jParser.nextToken();
if (jt == null)
break;
if (curObjPath.size() > 0) {
Object item = curObjPath.get(curObjPath.size() - 1);
if (item instanceof Integer) { // Increment array index in path
item = 1 + (Integer)item;
curObjPath.set(curObjPath.size() - 1, item);
updateLastPathItem(item, curTextPath);
}
}
if (jt == JsonToken.START_ARRAY || jt == JsonToken.START_OBJECT) {
if (jt == JsonToken.START_ARRAY) {
jGenerator.writeStartArray();
curObjPath.add(-1);
} else if (jt == JsonToken.START_OBJECT) {
jGenerator.writeStartObject();
curObjPath.add("");
}
curTextPath.append("/");
} else if (jt == JsonToken.END_ARRAY || jt == JsonToken.END_OBJECT) {
if (jt == JsonToken.END_ARRAY) {
jGenerator.writeEndArray();
} else if (jt == JsonToken.END_OBJECT) {
jGenerator.writeEndObject();
}
curObjPath.remove(curObjPath.size() - 1);
curTextPath.delete(curTextPath.lastIndexOf("/"), curTextPath.length());
} else if (jt == JsonToken.FIELD_NAME) {
String item = jParser.getText();
jGenerator.writeFieldName(item);
curObjPath.set(curObjPath.size() - 1, item);
updateLastPathItem(item, curTextPath);
} else {
if (path.equals(curTextPath.toString())) {
if (value == null) {
jGenerator.writeNull();
} else if (value instanceof Boolean) {
jGenerator.writeBoolean((Boolean)value);
} else if (value instanceof Short) {
jGenerator.writeNumber((Short)value);
} else if (value instanceof Integer) {
jGenerator.writeNumber((Integer)value);
} else if (value instanceof Long) {
jGenerator.writeNumber((Long)value);
} else if (value instanceof BigInteger) {
jGenerator.writeNumber((BigInteger)value);
} else if (value instanceof Float) {
jGenerator.writeNumber((Float)value);
} else if (value instanceof Double) {
jGenerator.writeNumber((Double)value);
} else if (value instanceof BigDecimal) {
jGenerator.writeNumber((BigDecimal)value);
} else if (value instanceof String) {
jGenerator.writeString((String)value);
} else {
throw new IllegalStateException("Unsupported type of substitution: " +
value.getClass().getName());
}
} else if (jt == JsonToken.VALUE_FALSE || jt == JsonToken.VALUE_TRUE) {
jGenerator.writeBoolean(jt == JsonToken.VALUE_TRUE);
} else if (jt == JsonToken.VALUE_NULL) {
jGenerator.writeNull();
} else if (jt == JsonToken.VALUE_STRING) {
jGenerator.writeString(jParser.getText());
} else if (jt == JsonToken.VALUE_NUMBER_INT) {
jGenerator.writeNumber(jParser.getBigIntegerValue());
} else if (jt == JsonToken.VALUE_NUMBER_FLOAT) {
jGenerator.writeNumber(jParser.getDecimalValue());
} else {
throw new IllegalStateException("Unsupported token type: " + jt.name());
}
}
}
jParser.close();
jGenerator.close();
}
private static void updateLastPathItem(Object item, StringBuilder sb) {
int pos = sb.lastIndexOf("/");
if (pos < 0)
throw new IllegalStateException("Unexpected internal state: " + sb);
String str = String.valueOf(item);
sb.replace(pos + 1, sb.length(), str.replace("~", "~0").replace("/", "~1"));
}
}
Upvotes: 1
Reputation: 36033
This is the first thing that comes to mind. However it has a learning curve. Personally I would write a small python script that walks the directory tree, reads the json in each file, updates the attribute, and writes it back. Should be some 10 lines. You can do it in any language though. Java would just be more verbose. The fact that you are using Spring and Hibernate sounds irrelevant, you want a separate little command line tool, right?
Upvotes: 1