Java Json beautifying on save - java

I am saving a player to a .json file like this:
public static void savePlayer(Player player) {
final String username = player.getUsername();
final byte[] json = new Gson().toJson(player).getBytes();
final String path = "pack/players/" + username;
try {
Files.write(Paths.get(path + "/data.json"), json, StandardOpenOption.CREATE);
logger.info("Successfully SAVED player [username=%s]!", username);
} catch (IOException e) {
e.printStackTrace();
}
}
and I am using this Eclipse JSON editor plugin to view the json file: https://sourceforge.net/projects/eclipsejsonedit/
However, when looking at the file it is all compressed in one line and not beautified.
The resulting one line of json code is printed like this (instead of beautified):
{"inventory":{"data":[null]},"equipment":{"data":[null]},"playerCredentials":{"username":"kay","password":"password"},"attribute":{}}
What can I do to beautify the code before saving it?

Since you are using Gson you can use their prettyPrinting and create a new Gson obejct
Gson gson = new GsonBuilder().setPrettyPrinting().create();
And then create a String object from that
String output = gson.toJson(json);
If you use FileWriter you can simple use that string to write to a file.

Related

Jackson doesn't append new JSON object to exisiting Json file

I'm trying to build a Springboot app that allows to insert Json object from Postman and save it to existing json file that has other data. I'm new to Jackson so perhaps I missed something?
this is how my json file looks:
[
{
"Name":"After Dark",
"Author":"Haruki Murakami"
},
{
"Name":"It",
"Author":"Stephen King"
}
]
This is what I have tried:
#PostMapping("/insertBook")
public void insertBook(#RequestBody Book book) {
File booksJsonFile = Paths.get(this.getClass().getResource("/books.json").toURI()).toFile();
objectMapper.writeValue(booksJsonFile, book);
}
It's inserts to an empty file but it's doesn't append to existing json file.
I also have tried this:
#PostMapping("/insertBook")
public void insertBook(#RequestBody Book book) throws URISyntaxException {
try {
File file = Paths.get(this.getClass().getResource("/books.json").toURI()).toFile();
FileWriter fileWriter = new FileWriter(file, true);
SequenceWriter seqWriter = objectMapper.writer().writeValuesAsArray(fileWriter);
seqWriter.write(book);
seqWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
This is what I'm sending from Postman:
Do I need to use something else to achieve the result that I want?
I will be thankfull for your help.
I have tried to reproduce your problem according to your code and I come to following conclusions:
You can not modify file under resources directly. Here is explanation why.
I managed to append new JSON to the file (using your approach but saving file locally) but it's probably not what you expect (json structure is corrupted):
[
{
"Name":"After Dark",
"Author":"Haruki Murakami"
},
{
"Name":"It",
"Author":"Stephen King"
}
][{"Name":"new name","Author":"new author"}]
I am afraid that it is not possible to update current JSON structure directly in the file.
I managed to solve your problem using org.json library. However, the disadvantage of my solution is necessity of rewriting entire file each time. In addition I used synchronized keyword in order to avoid simultaneous file modification.
public synchronized void updateJsonFile(Book book) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Path path = Paths.get("./books.json");
final String currentJsonArrayAsString = Files.readString(path);
try (FileWriter fileWriter = new FileWriter(path.toFile(), false)) {
JSONObject jsonObject = new JSONObject(objectMapper.writeValueAsString(book));
JSONArray jsonArray = new JSONArray(currentJsonArrayAsString);
jsonArray.put(jsonObject);
fileWriter.write(jsonArray.toString());
}
}
And now the books.json has following content:
[
{
"Author":"Haruki Murakami",
"Name":"After Dark"
},
{
"Author":"Stephen King",
"Name":"It"
},
{
"Author":"new author",
"Name":"new name"
}
]

How to Update JSON value using Java

I have below json, i want to update each and every value of that json but sometimes only one value
{
"msgType": "NEW",
"code": "205",
"plid": "PLB52145",
}
I've already tried to update using below code
FileReader reader = new FileReader(filePath);
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader);
System.out.println(jsonObject);
long id =Long.valueOf((String) idNewObj.get("plid"));
System.out.println(plid);
idNewObj.put("plid",PL809809809);
System.out.println(jsonObject);
To make transformation/filtering of JSON files, I'd suggest to use stream/event-oriented parsing and generating rather than any object mapping. Just an example, which uses simple and lightweight JSON parser https://github.com/anatolygudkov/green-jelly :
import org.green.jelly.AppendableWriter;
import org.green.jelly.JsonEventPump;
import org.green.jelly.JsonParser;
import java.io.StringWriter;
import java.io.Writer;
public class UpdateMyJson {
private static final String jsonToUpdate = "{\n" +
"\"msgType\": \"NEW\",\n" +
"\"code\": \"205\",\n" +
"\"plid\": \"PLB52145\",\n" +
"}";
public static void main(String[] args) {
final StringWriter result = new StringWriter();
final JsonParser parser = new JsonParser();
parser.setListener(new MyJsonUpdater(result));
parser.parse(jsonToUpdate); // if you read a file with a buffer,
// call parse() several times part by part in a loop until EOF
parser.eoj(); // and then call .eoj()
System.out.println(result);
}
static class MyJsonUpdater extends JsonEventPump {
private boolean isPlid;
MyJsonUpdater(final Writer output) {
super(new AppendableWriter<>(output));
}
#Override
public boolean onObjectMember(final CharSequence name) {
isPlid = "plid".contentEquals(name);
return super.onObjectMember(name);
}
#Override
public boolean onStringValue(final CharSequence data) {
if (isPlid) {
if ("PLB52145".contentEquals(data)) {
return super.onStringValue("PL809809809");
}
}
return super.onStringValue(data);
}
}
}
Props:
the file/data doesn't require to be loaded entirely into memory, you can process megs/gigs with no problems
it works much more faster, especially for large files
it's easy to implement any custom type/rule of transformation with this pattern
Both of standard Gson and Jackson libs also provide tokenizers to work with JSON in streaming manner.
UPDATED: JsonEventPump used
You need to write the updated JSON into the file from where JSON was read. Also, I did not understand your variable assignment so I have updated that as well. Use below code:
FileReader reader = new FileReader(filePath);
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader);
System.out.println(jsonObject);
long id =Long.valueOf((String) idNewObj.get("plid"));
System.out.println(id);
jsonObject.put("plid",PL809809809);
System.out.println(jsonObject);
FileWriter writer = new FileWriter(filePath, false); //overwrites the content of file
writer.write(jsonObject.toString());
writer.close();

dynimacally generte a json object

String json = "{\"loginForm\": [{\"formType\": \"questionAndAnswer\",\"id\": 164422,\"row\": [{\"label\": \"What is the name of your state?\",\"field\": [{\"id\":\"SQandA--QUESTION_1-1\",\"value\": \""+answer1+"\"}]},{\"label\": \"What is the name of your first school\",\"field\": [{\"id\":\"SQandA--QUESTION_2-2\",\"value\": \""+answer2+"\"}]}]}],"+dataset+"}";
this json contains questions and answer in it and its hard coded in my code what should i do to dynamically generate it as i want to remove the hard code and call it dynamically.
You can create a class file with your json fields and then convert the class object to json using Jackson apis.
private String getJsonFromJava (Object obj) {
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "";
try {
jsonInString = mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
System.out.println("Unable to parse object to prepare JSON string", e);
}
return jsonInString;
}
You need to write logic to create json using the inputs. If you are creating the json in JS then look at sample code below. Or you can do the same login in server side - java etc?
function createJSON() {
jsonObj = [];
$("input[questions]").each(function() {
var q= $(this).attr("Question");
var ans= $(this).val();
item = {}
item ["question"] = id;
item ["answer"] = ans;
jsonObj.push(item);
});
console.log(jsonObj);
}

My Json created in Gson comes out in a single line when I look at it in the web

I am creating a RESTful web service using java, MySQ, Jersey, and Gson. It works but my only problem is when I run it on the server and go to the localhost site of my project the JSON is all in one line.
This is the output of the JSON on the web.
"[\n{\n\"id\":5,\n\"subject\":\"Math\",\n\"subjectAcronym\":\"MT\",\n\"classNumber\":2550,\n\"className\":\"Linear Algebra\",\n\"unit\": 3,\n\"prerequisite\":true,\n\"corequisite\":false\n}\n]"
This is the class in the code.
#GET
#Path("/Classes")
#Produces("application/json")
public String feed() {
String feeds = null;
try {
ArrayList<ClassList> feedData = null;
ClassManager projectManager = new ClassManager();
feedData = projectManager.GetFeeds();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(feedData));
feeds = gson.toJson(feedData);
}
catch (Exception e) {
System.out.println("Exception Error"); // Console
}
return feeds;
}
The GsonBuilder().setPrettyPrinting() in the code prints out in the console the way I want it to print out in the web.
The output in the console of eclipse.
[
{
"id": 5,
"subject": "Math",
"subjectAcronym": "MT",
"classNumber": 2550,
"className": "Linear Algebra",
"unit": 3,
"prerequisite": true,
"corequisite": false
}
]
I have 2 more classes similar to this one and all show up the same on the web(in a single line). How can make show on the web like a output in the console? Any response is helpful. Thank you.
That's because your JSON is a string because you set your GsonBuilder to pretty print, which adds newlines and formatting and such. You want to write the JSON with no formatting so it is JSON and not a string. You can also pretty print if you wish. I believe this will solve your problem:
#GET
#Path("/Classes")
#Produces("application/json")
public String feed() {
String feeds = null;
try {
ArrayList<ClassList> feedData = null;
ClassManager projectManager = new ClassManager();
feedData = projectManager.GetFeeds();
Gson gson_pretty = new GsonBuilder().setPrettyPrinting().create();
Gson gson = new Gson();
System.out.println(gson_pretty.toJson(feedData));
feeds = gson.toJson(feedData);
}
catch (Exception e) {
System.out.println("Exception Error"); // Console
}
return feeds;
}
Note that on Google Chrome, JSON is represented on one line. Here is an extension to change that. Firefox displays JSON by default like this:

Any method of passing the Json data in URL format using JSONObject?

I create a java URL class which contain my Json data and have some function to obtain back my json data for doing some data comparison, I found out it's might not support by JSONObject for passing the data into the JSONObject. Do I need to use JSONArray in my case because my JSON data have array structure as well?
try
{
JSONObject obj = new JSONObject ();
obj.readJsonFromUrl(theUrl);
System.out.println(obj.toString());
}
catch(MalformedURLException e)
{
System.out.print("your problem here ...1");
}
}
else
{
System.out.print("Can't Connect");
}
I am sure that this is the place give me the error message because it return me this error in my compiler
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method readJsonFromUrl(URL) is undefined for the type JSONObject
there are also some warning message for that the JSONObject readJsonFromUrl method
private static JSONObject readJsonFromUrl(URL theUrl) throws IOException, JSONException {
Anyone can provide me the explaination of how the JSON data work in java? I saw quite number of Java class for JSON which make me confuse for it such as JSONObject, JSONArray , JSONValue. I search some information online but I also not very clear about it since I am very new to JSON data processing This is my sample json data and the data I need is scan_result only
{
"data_id":"a71a3c2588c6472bb4daea41a0b58835",
"file_info":{
"display_name":"",
"file_size":242,
"file_type":"Not available",
"file_type_description":"Not available",
"md5":"aa69ba384f22d0dc0551ace2fbb9ad55",
"sha1":"09ceb54e65df3d3086b222e8643acffe451a6e8a",
"sha256":"dcb46d6ae2a187f789c12f19c44bbe4b9a43bd200a3b306d5e9c1fcf811dc430",
"upload_timestamp":"2016-11-18T09:09:08.390Z"
},
"process_info":{
"blocked_reason":"",
"file_type_skipped_scan":false,
"post_processing":{
"actions_failed":"",
"actions_ran":"",
"converted_destination":"",
"converted_to":"",
"copy_move_destination":""
},
"profile":"File scan",
"progress_percentage":100,
"result":"Allowed",
"user_agent":""
},
"scan_results":{
"data_id":"a71a3c2588c6472bb4daea41a0b58835",
"progress_percentage":100,
"scan_all_result_a":"No Threat Detected",
"scan_all_result_i":0,
"scan_details":{
"Ahnlab":{
"def_time":"2016-11-08T15:00:00.000Z",
"location":"local",
"scan_result_i":0,
"scan_time":1,
"threat_found":""
},
"Avira":{
"def_time":"2016-11-08T00:00:00.000Z",
"location":"local",
"scan_result_i":0,
"scan_time":133,
"threat_found":""
},
"ClamAV":{
"def_time":"2016-11-08T10:28:00.000Z",
"location":"local",
"scan_result_i":0,
"scan_time":94,
"threat_found":""
},
"ESET":{
"def_time":"2016-11-08T00:00:00.000Z",
"location":"local",
"scan_result_i":0,
"scan_time":38,
"threat_found":""
}
},
"start_time":"2016-11-18T09:09:08.405Z",
"total_avs":4,
"total_time":250
},
"vulnerability_info":{
}
}
As mentioned here, there are many ways to solve this. Either you have to implement the read, parse operations yourself (#Roland Illig 's answer)
//you have to implement the readJSON method
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
Or you could use a library. The most well-known and widely used libraries are jackson and gson.
The big picture is that you try to "map" your json Object to a class.
You have your json file:
{
"id":1,
"name":"eirini",
"hobbies":["music","philosophy","football"]
}
and a class that represents this file and will store the values (depending on the library that you use there might be different requirements, for example getters, setters etc..)
public class Person {
public int id;
public String name;
public List<String> hobbies = new ArrayList<String>();
public String toString() {
return name +" has the id: " + id + " the following hobbies" + hobbies.get(0) + " " + hobbies.get(2);
}
}
Finally in your main method:
public static void main(String[] args) throws IOException, ParseException {
ObjectMapper mapper = new ObjectMapper();
InputStream input = this.getClass().getResourceAsStream(FILE); //read your file. There are many ways to achieve this.
ObjectMapper mapper = new ObjectMapper(); // just need one
Person eirini = mapper.readValue(input, Person.class);
System.out.println(eirini.toString());
You cannot pass json in url, you can pass it in body. Writing Json to stream body and post it using regular java method.
Here is oracle community url of explanation of your problem.
Required Jar can be downloaded from here.
Test Code Follows:
URL url = new URL("https://graph.facebook.com/search?q=java&type=post");
try (InputStream is = url.openStream();
JsonReader rdr = Json.createReader(is)) {
JsonObject obj = rdr.readObject();
JsonArray results = obj.getJsonArray("data");
for (JsonObject result : results.getValuesAs(JsonObject.class)){
System.out.print(result.getJsonObject("from").getString("name"));
System.out.print(": ");
System.out.println(result.getString("message", ""));
System.out.println("-----------");
}
}

Categories