Hey I was wondering if it is possible to edit an existing json I know the location off.
So lets say that the location is C:\Something.json
then how do I edit it ??.
Thanks
If you want to edit complex JSON structure I would recommend using GSON library. You can then perform the following steps :
Gson gson = new Gson();
String yourfilecontents; //read contents from File
1) read JSON File and convert it into an object structure.
YourObject obj = gson.fromJson(yourfilecontents, YourObject.class);
2) Modify the object as per your requirement.
obj.field1(newValue);
3) Convert the object into JSON
String newJson = gson.toJson(obj);
4) Write the JSON (newJson) back to the file
Your question is very unprecise, but here are some tips, you can:
Open the JSON file with your favourite notepad
Use java.io.File API to open the file
Use some JSON Java API
To transform/filter JSON, especially in case of large files, it isn't a good idea to load the whole file to memory and use object mapping at all. Prefer stream oriented parsing and generating. For example, both Gson and Jackson support such technique. To illustrate the idea I use small, fast and GC-free library https://github.com/anatolygudkov/green-jelly. I've taken a question Loop and edit json file in java The code renames all property names "div" to "b-div"
import org.green.jelly.*;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
public class Transformation {
public static void main(final String[] args) throws IOException {
final String inputContent = "{ \n" +
" \"html\":{ \n" +
" \"child\":[ \n" +
" { \n" +
" \"head\":{ \n" +
"\n" +
" }\n" +
" },\n" +
" { \n" +
" \"body\":{ \n" +
" \"child\":[ \n" +
" { \n" +
" \"div\":{ \n" +
" \"id\":\"intk\",\n" +
" \"class\":\"akagen-row b-table\",\n" +
" \"child\":[ \n" +
" { \n" +
" \"div\":{ \n" +
" \"id\":\"aaaaa\",\n" +
" \"title\":\"bbbbbbb\",\n" +
" \"class\":\"akagen-cell\"\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
" },\n" +
" { \n" +
" \"div\":{ \n" +
" \"class\":\"akagen-row b-table\",\n" +
" \"child\":[ \n" +
" { \n" +
" \"div\":{ \n" +
" \"class\":\"akagen-cell\"\n" +
" }\n" +
" },\n" +
" { \n" +
" \"div\":{ \n" +
" \"class\":\"akagen-cell\"\n" +
" }\n" +
" },\n" +
" { \n" +
" \"div\":{ \n" +
" \"class\":\"akagen-cell\"\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
"}";
final Reader input = new StringReader(inputContent); // replace by FileReader
final Writer output = new StringWriter(); // replace by FileWriter
final JsonGenerator generator = new JsonGenerator();
generator.setOutput(new AppendableWriter<>(output));
final JsonParser parser = new JsonParser().setListener(new JsonParserListener() {
#Override
public void onJsonStarted() {
generator.reset();
}
#Override
public void onError(final String error, final int position) {
}
#Override
public void onJsonEnded() {
generator.eoj();
}
#Override
public boolean onObjectStarted() {
generator.startObject();
return true;
}
#Override
public boolean onObjectMember(final CharSequence name) {
if ("div".contentEquals(name)) {
generator.objectMember("b-div");
} else {
generator.objectMember(name);
}
return true;
}
#Override
public boolean onObjectEnded() {
generator.endObject();
return true;
}
#Override
public boolean onArrayStarted() {
generator.startArray();
return true;
}
#Override
public boolean onArrayEnded() {
generator.startArray();
return true;
}
#Override
public boolean onStringValue(final CharSequence data) {
generator.stringValue(data);
return true;
}
#Override
public boolean onNumberValue(final JsonNumber number) {
generator.numberValue(number);
return false;
}
#Override
public boolean onTrueValue() {
generator.trueValue();
return true;
}
#Override
public boolean onFalseValue() {
generator.falseValue();
return true;
}
#Override
public boolean onNullValue() {
generator.nullValue();
return true;
}
});
final CharArrayCharSequence buffer = new CharArrayCharSequence(1024 * 8);
int length;
while ((length = input.read(buffer.getChars())) != -1) {
buffer.setLength(length);
parser.parse(buffer);
}
parser.eoj();
System.out.println(output.toString());
}
}
Performance of such lightweight technique of transformation is almost the highest in terms of both CPU utilization and memory footprint you can reach in Java (with no tricks like SIMD over JNI).
Related
private static CodeList prepareChangeObject(CodeList codeList, CodeList existingCodeList, boolean dataExists)
throws EntityValidationException {
CodeList UpdatedCodeList = new CodeList();
BeanUtils.copyProperties(codeList, UpdatedCodeList);
Set<CodeListData> updatedDataList =UpdatedCodeList.getData().stream().collect(Collectors.toSet());
updatedDataList.addAll(existingCodeList.getData());
List<CodeListData> finalData = updatedDataList.stream().collect(
collectingAndThen(toCollection(() -> new TreeSet<>(comparing(CodeListData::getKey))), ArrayList::new));
finalData = finalData.stream().filter(data -> {
if (data.getOperation() == null)
data.setOperation(MetaConstants.OPERATION_ADD);
if (null != data.getOperation()) {
if (data.getOperation().equals(MetaConstants.OPERATION_DELETE) && dataExists)
exceptionMessagesList.add(
new ExceptionMessage("foundation.OperationNotAllowed", new String[] { data.getKey() }));
if (data.getOperation().equals(MetaConstants.OPERATION_DELETE) && !dataExists)
return false;
if (data.getOperation().equals(MetaConstants.OPERATION_ADD))
return true;
}
return false;
}).collect(Collectors.toList());
UpdatedCodeList.setData(finalData);
if(!CollectionUtils.isEmpty(exceptionMessagesList))
throw new EntityValidationException(HTTPClientError.BAD_REQUEST, exceptionMessagesList);
return UpdatedCodeList;
}
1.The above method should return a change object based on the operation specified.
public static void main(String[] args) throws JsonMappingException, JsonProcessingException, EntityValidationException {
String jsonPost = "{\n"
+ " \"id\": \"temperature101\",\n"
+ " \"descriptions\": [\n"
+ " {\n"
+ " \"languageCode\": \"en\",\n"
+ " \"description\": \"description\",\n"
+ " \"longDescription\": \"long description\"\n"
+ " },\n"
+ " {\n"
+ " \"languageCode\": \"de\",\n"
+ " \"description\": \"description\",\n"
+ " \"longDescription\": \"long description\"\n"
+ " }\n"
+ " ],\n"
+ " \"dataType\": \"String\",\n"
+ " \"data\": [\n"
+ " {\n"
+ " \"key\": \"val1\",\n"
+ " \"value\": \"High\"\n"
+ " },\n"
+ " {\n"
+ " \"key\": \"val4\",\n"
+ " \"value\": \"Medium\"\n"
+ " },\n"
+ " {\n"
+ " \"key\": \"val3\",\n"
+ " \"value\": \"Low\"\n"
+ " }\n"
+ " ]\n"
+ "}";
String jsonPatch = "{\n"
+ " \"id\": \"temperature101\",\n"
+ " \"descriptions\": [\n"
+ " {\n"
+ " \"languageCode\": \"en\",\n"
+ " \"description\": \"description1\",\n"
+ " \"longDescription\": \"long description1\"\n"
+ " },\n"
+ " {\n"
+ " \"languageCode\": \"de\",\n"
+ " \"description\": \"description1\",\n"
+ " \"longDescription\": \"long description1\"\n"
+ " }\n"
+ " ],\n"
+ " \"dataType\": \"String\",\n"
+ " \"data\": [\n"
+ " {\n"
+ " \"key\": \"val1\",\n"
+ " \"value\": \"High\",\n"
+ " \"operation\": \"DELETE\"\n"
+ "\n"
+ " },\n"
+ " {\n"
+ " \"key\": \"val4\",\n"
+ " \"value\": \"Medium\",\n"
+ " \"operation\": \"DELETE\"\n"
+ " }\n"
+ " ]\n"
+ "}";
ObjectMapper mapper = new ObjectMapper();
CodeList ExistingodeList = mapper.readValue(jsonPost, CodeList.class);
CodeList currentCodeList = mapper.readValue(jsonPatch, CodeList.class);
CodeList upDatetedCodeList = prepareChangeObject(currentCodeList, ExistingodeList, false);
Gson gson = new Gson();
System.out.println(upDatetedCodeList.toString());
System.out.println(gson.toJson(upDatetedCodeList));
}
the above main method to test the code
#Data
public class CodeListData {
#Column("ID")
#JsonIgnore
private String id;
#Column("KEY")
private String key;
#Column("VALUE")
private String value;
#Column("ETAG")
#JsonIgnore
private String etag;
#JsonIgnore
#Column("VERSION")
#Version
private Long version;
#Transient
#JsonProperty(access = Access.WRITE_ONLY)
private String operation;
}
Pojo for reference
#Data
public class CodeList implements Persistable<String>{
#NotNull
#Id
#Column("ID")
private String id;
#MappedCollection(idColumn = "ID", keyColumn = "ID_SEQ")
private List<CodeListDescriptions> descriptions = new ArrayList<>();
#Column("DATA_TYPE")
private String dataType;
#Column("LENGTH")
private String length;
#MappedCollection(idColumn = "ID", keyColumn = "ID_SEQ")
private List<CodeListData> data = new ArrayList<CodeListData>();
#JsonIgnore
#Column("VERSION")
private Long version;
#Column("ETAG")
#JsonIgnore
private String etag;
#Transient
#JsonIgnore
#Setter
private boolean isInsert;
#JsonIgnore
public boolean isNew() {
return isInsert;
}
}
4.codeList pojo
#Data
public class CodeListDescriptions{
#Column("ISO")
public String languageCode;
#Column("DESCRIPTION")
public String description;
#Column("LONG_DESCRIPTION")
public String longDescription;
#Column("ID")
#JsonIgnore
private String id;
}
5.final output required is only "val3" to be present. The method is supposed to remove or add based on the operations DELETE or ADD. The issue is that val4 is still in the output because when the finalData is created it prefers to keep the "val4" from existing data which does not contain any operation. The final output needs to contain the added values and values not specified in the payload but exists in the first one.
it prefers to keep the val4 from existing data which does not contain any operation
you are defaulting to the add operation with this code, so regardless of whether or not there is an operation, you explicitly set one
if (data.getOperation() == null)
data.setOperation(MetaConstants.OPERATION_ADD);
Then you check it like
if (null != data.getOperation()) { // this is always true, because you use the default one line before
...
if (data.getOperation().equals(MetaConstants.OPERATION_ADD))
return true;
}
so in the end the final
return false;
will never be reached.
You create a Set<CodeListData> from both the existing and the update data set. CodeListData defines its equals and hashCode methods over all fields. Note that Lombok ignores transient fields, but those a different from fields annotated with #Transient. So you have val4 twice in the Set once with DELETE operation and once without any operation. The one with DELETE will get filtered out, but the one with no operation will default to ADD and stay in the SET.
Note: I consider it unfortunate to name a variable of type Set anything that ends in List.
I've a JSON:
{
"payment_intent": {
"amount": "Amount",
"currency_code": "840",
"invoice_number": "pay-automation-invoice-no-01",
"payment_intent_id": "pay-automation-return-intent-id-01",
"intent_reference_id": "pay-automation-intent-reference-id-01"
},
"payment_refundable_intents": {
"transactions": {
"sales": "pay-automation-sales"
}
}
}
Now, when I tried to replace string "pay-automation-sales" with JSONArray using
payloadJson = payloadJson.replaceAll("pay-automation-sales", salesString);
salesString is
[{"amount":"200.0","payment_intent_id":"29518150","tender_type":"cash","reference_id":"db79893a-9fe0-4391-91f8-fbc-cash-6c88-66db","intent_reference_id":"db79893a-9fe0-4391-91f8-fbc7945ce446","id":"000000893275","status":"Approved"},{"amount":"800.0","payment_intent_id":"29518150","tender_type":"cash","reference_id":"db79893a-9fe0-4391-91f8-fbc-cash-1d12-8466","intent_reference_id":"db79893a-9fe0-4391-91f8-fbc7945ce446","id":"000000893282","status":"Approved"}]
Here, payloadJson is of type String. The replaceAll works fine but actually I want to pass "sales" as an array of object in JSON. But it is getting passed like this and it's not a valid JSON format. Double quotes in value of sales key in JSON causes an issue I think.
"sales": "[{"amount":"200.0","payment_intent_id":"29518150","tender_type":"cash","reference_id":"db79893a-9fe0-4391-91f8-fbc-cash-6c88-66db","intent_reference_id":"db79893a-9fe0-4391-91f8-fbc7945ce446","id":"000000893275","status":"Approved"},{"amount":"800.0","payment_intent_id":"29518150","tender_type":"cash","reference_id":"db79893a-9fe0-4391-91f8-fbc-cash-1d12-8466","intent_reference_id":"db79893a-9fe0-4391-91f8-fbc7945ce446","id":"000000893282","status":"Approved"}]"
How do I replace string in JSON with valid JSON array of objects?
Since you're working with String objects here and not some form of JSON object model, when you did
payloadJson = payloadJson.replaceAll("pay-automation-sales", salesString);
it found the string
pay-automation-sales
within payloadJson and replaced it verbatin with the contents of salesString. Notice that you did NOT tell it to include the quotes in the original string in the part being replaced.
It should be
payloadJson = payloadJson.replaceAll("\"pay-automation-sales\"", salesString);
You would probably be better off using a real JSON library that understands JSON syntax and can manipulate the JSON as an in-memory document model.
Using Java String
public class StringDemo {
static final String originalJson = " {\n"
+ " \"payment_intent\": {\n"
+ " \"amount\": \"Amount\",\n"
+ " \"currency_code\": \"840\",\n"
+ " \"invoice_number\": \"pay-automation-invoice-no-01\",\n"
+ " \"payment_intent_id\": \"pay-automation-return-intent-id-01\",\n"
+ " \"intent_reference_id\": \"pay-automation-intent-reference-id-01\"\n"
+ " },\n"
+ " \"payment_refundable_intents\": {\n"
+ " \"transactions\": {\n"
+ " \"sales\": \"pay-automation-sales\"\n"
+ " }\n"
+ " }\n"
+ "}";
static final String originalArray = "[{\"amount\":\"200.0\",\"payment_intent_id\":\"29518150\",\"tender_type\":\"cash\",\"reference_id\":\"db79893a-9fe0-4391-91f8-fbc-cash-6c88-66db\",\"intent_reference_id\":\"db79893a-9fe0-4391-91f8-fbc7945ce446\",\"id\":\"000000893275\",\"status\":\"Approved\"},{\"amount\":\"800.0\",\"payment_intent_id\":\"29518150\",\"tender_type\":\"cash\",\"reference_id\":\"db79893a-9fe0-4391-91f8-fbc-cash-1d12-8466\",\"intent_reference_id\":\"db79893a-9fe0-4391-91f8-fbc7945ce446\",\"id\":\"000000893282\",\"status\":\"Approved\"}]";
public static void main(String[] args) {
String editedJson = originalJson.replaceAll("\"pay-automation-sales\"", originalArray);
System.out.println(editedJson);;
}
}
Using Jackson
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
public class JacksonDemo {
static final String originalJson = " {\n"
+ " \"payment_intent\": {\n"
+ " \"amount\": \"Amount\",\n"
+ " \"currency_code\": \"840\",\n"
+ " \"invoice_number\": \"pay-automation-invoice-no-01\",\n"
+ " \"payment_intent_id\": \"pay-automation-return-intent-id-01\",\n"
+ " \"intent_reference_id\": \"pay-automation-intent-reference-id-01\"\n"
+ " },\n"
+ " \"payment_refundable_intents\": {\n"
+ " \"transactions\": {\n"
+ " \"sales\": \"pay-automation-sales\"\n"
+ " }\n"
+ " }\n"
+ "}";
static final String originalArray = "[{\"amount\":\"200.0\",\"payment_intent_id\":\"29518150\",\"tender_type\":\"cash\",\"reference_id\":\"db79893a-9fe0-4391-91f8-fbc-cash-6c88-66db\",\"intent_reference_id\":\"db79893a-9fe0-4391-91f8-fbc7945ce446\",\"id\":\"000000893275\",\"status\":\"Approved\"},{\"amount\":\"800.0\",\"payment_intent_id\":\"29518150\",\"tender_type\":\"cash\",\"reference_id\":\"db79893a-9fe0-4391-91f8-fbc-cash-1d12-8466\",\"intent_reference_id\":\"db79893a-9fe0-4391-91f8-fbc7945ce446\",\"id\":\"000000893282\",\"status\":\"Approved\"}]";
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(originalJson);
JsonNode array = mapper.readTree(originalArray);
ObjectNode transactions = (ObjectNode) root.findValue("transactions");
transactions.set("sales", array);
String editedJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);
System.out.println(editedJson);;
}
}
I have a list of json records, for instance:
[{“age”:27,”lastname”:”Robert “,”firstName”:”Rob”,”company”:”abc”},
{“age”:27,”lastname”:”Ashok “,”firstName”:”Bob”,”company”:”def”},
{“age”:27,”lastname”:”murali“,”firstName”:”Got”,”company”,”Ghori”}]
Write a method which takes lastName as parameter and based on that input I need to get only that particular record out and get it displayed
Your probleme is not well explained, you can try this solution (after correcting your string to be a real json content)
Using ObjectMapper you can read your string to transform it to an ArrayNode
public static void main(String[] args) throws IOException {
String json= "[\n" +
" {\n" +
" \"age\":27,\n" +
" \"lastname\":\"Robert \",\n" +
" \"firstName\":\"Rob\",\n" +
" \"company\":\"abc\"\n" +
" },\n" +
" {\n" +
" \"age\":27,\n" +
" \"lastname\":\"Ashok \",\n" +
" \"firstName\":\"Bob\",\n" +
" \"company\":\"def\"\n" +
" },\n" +
" {\n" +
" \"age\":27,\n" +
" \"lastname\":\"murali\",\n" +
" \"firstName\":\"Got\",\n" +
" \"company\":\"\"\n" +
" }\n" +
"]";
// example with murali
getLine(json, "murali");
}
private static String getLine(String json, String lastName) throws IOException {
ArrayNode rootNode = (ArrayNode) new ObjectMapper().readTree(json);
for(JsonNode jsonNode : rootNode) {
ObjectNode node = (ObjectNode)jsonNode;
String lastNameValue = node.get("lastname").textValue();
if(lastName.equals(lastNameValue)){
return jsonNode.toString();
}
}
return null;
}
the result for this example is :
{"age":27,"lastname":"murali","firstName":"Got","company":""}
I have JSON string that needs to be converted in Java object using Google Gson library.
I am stuck in converting due to forward slash in the following JSON string.
{
"status":"200",
"results":{
"resultitems":[
{
"uri":"/document/id/e20a8dad50d91a839c50ab5f323f3df3",
"path":"Data/xyz/abcdata",
"metadata":{
"data/category/item":"yahoo/post",
"ast_id":"67677"
}
}
]
}
Indeed, for Data/category/item, I am getting a null value. How can I correctly parse it?
Just a starting note: the JSON you put in request is not a valid JSON, but can be easily fixed adding a brace (I used fixed JSON in my answer).
I suggest you to parse your JSON this way. Declare the following classes.
public class Container {
public int status;
public Results results;
#Override
public String toString() {
return "Container [status=" + status + ", results=" + results + "]";
}
}
public class Results {
public List<ResultItem> resultitems;
#Override
public String toString() {
return "Results [resultitems=" + resultitems + "]";
}
}
public class ResultItem {
String uri;
String path;
HashMap metadata;
#Override
public String toString() {
return "ResultItem [uri=" + uri + ", path=" + path + ", metadata="
+ metadata + "]";
}
}
and then call this code:
public class Q19684865 {
public static void main(String[] args) {
String json = " { "
+ " \"status\":\"200\", "
+ " \"results\":{ "
+ " \"resultitems\":[ "
+ " { "
+ " \"uri\":\"/document/id/e20a8dad50d91a839c50ab5f323f3df3\", "
+ " \"path\":\"Data/xyz/abcdata\", "
+ " \"metadata\":{ "
+ " \"data/category/item\":\"yahoo/post\", "
+ " \"ast_id\":\"67677\" "
+ " } "
+ " } "
+ " ] "
+ " } "
+ " } ";
Container c = new Gson().fromJson(json, Container.class);
System.out.println("this is the parsed json: " +c);
System.out.println("this is the property 'data/category/item': "+c.results.resultitems.get(0).metadata.get("data/category/item"));
}
and this is the result:
this is the parsed json: Container [status=200, results=Results [resultitems=[ResultItem [uri=/document/id/e20a8dad50d91a839c50ab5f323f3df3, path=Data/xyz/abcdata, metadata={data/category/item=yahoo/post, ast_id=67677}]]]]
this is the property 'data/category/item': yahoo/post
Explanation: normally you need just POJOs if you do not have particular needs, where POJO field name corresponds to the label of the JSON value. But 'data/category/item' cannot be a valid Java identifier. So I chose to parse to a Map.
A second way could be to replace in JSON string your "data/category/item" with a valid Java identifier, "data_category_item" for example or, if you can change JSON origin, do the same at the source.
The json looks like this :
"hour_totals": {
"382423": {
"imp": 126,
"clk": 1,
"spend": "$0.03",
"conv": 0,
"cpm": "$0.22",
"cpc": "$0.03",
"ctr": "0.79%",
"cpa": "$Inf"
},
"382424": {
"imp": 209,
"clk": 1,
"spend": "$0.05",
"conv": 0,
"cpm": "$0.23",
"cpc": "$0.05",
"ctr": "0.48%",
"cpa": "$Inf"
}}
I read more than 20 answers, but unable to find how to deserialize such a structure, please help on what would the class look like since the hour is not a fixed string.
To parse this JSON with Gson you need two steps.
Define this classes:
public class Total {
Map<String, HourData> hour_totals;
#Override
public String toString() {
return "Total [hour_totals=" + hour_totals + "]";
}
}
where HourData is
public class HourData {
Integer imp;
Integer clk;
String spend;
Integer conv;
String cpm;
String cpc;
String cpa;
#Override
public String toString() {
return "HourData [imp=" + imp + ", clk=" + clk + ", spend=" + spend
+ ", conv=" + conv + ", cpm=" + cpm + ", cpc=" + cpc + ", cpa="
+ cpa + "]";
}
}
Hack a bit your "Json string" since it's not a valid Json (see more details below). You just need to add braces like this code:
public class Q19201300 {
public static void main(String[] args) {
String json = "\"hour_totals\": { "
+ " \"382423\": { "
+ " \"imp\": 126, "
+ " \"clk\": 1, "
+ " \"spend\": \"$0.03\", "
+ " \"conv\": 0, "
+ " \"cpm\": \"$0.22\", "
+ " \"cpc\": \"$0.03\", "
+ " \"ctr\": \"0.79%\", "
+ " \"cpa\": \"$Inf\" "
+ "}, "
+ "\"382424\": { "
+ " \"imp\": 209, "
+ " \"clk\": 1, "
+ " \"spend\": \"$0.05\", "
+ " \"conv\": 0, "
+ " \"cpm\": \"$0.23\", "
+ " \"cpc\": \"$0.05\", "
+ " \"ctr\": \"0.48%\", "
+ " \"cpa\": \"$Inf\" "
+ "}} ";
Total t = new Gson().fromJson("{" + json + "}", Total.class);
System.out.println(t);
}
}
This will give you:
Total [hour_totals={382423=HourData [imp=126, clk=1, spend=$0.03,
conv=0, cpm=$0.22, cpc=$0.03, cpa=$Inf], 382424=HourData [imp=209,
clk=1, spend=$0.05, conv=0, cpm=$0.23, cpc=$0.05, cpa=$Inf]}]
About your string. From JSON official grammar (http://www.ietf.org/rfc/rfc4627.txt):
JSON Grammar
A JSON text is a sequence of tokens. The set of tokens includes
six structural characters, strings, numbers, and three literal
names.
A JSON text is a serialized object or array.