I am creating a program whereby I need to save(write) objects to a JSON, and then load(read) these objects back into the program. I have told that GSON is a good way to do this. However, I am having some troubles with it. I have tried the following:
Gson g = new Gson();
try (FileWriter writer = new FileWriter(file)) {
String j = g.toJson(board);
writer.write(j);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
When I run the program, I get the error:
class object3 declares multiple JSON fields named state
The object I am trying to write to the JSON has an ID, and an Array of another Object (object2), and each of these objects have an Array of another Object (object3). object3 has multiple fields, mostly strings. What is the simplest way for me to write an object such as this to a JSON file and then be able to read it back into my program?
If you simply want to serialize and deserialize object state in a JSON format, and don't care too much about the exact shape of the JSON, XStream makes this very easy. It tolerates almost any Java object structure and isn't as pernickety as Gson.
It was originally designed to serialize to XML, but if you use the JettisonMappedXmlDriver it will output JSON instead. I have found it to be a well-written and reliable library.
Product product = new Product("Banana", "123", 23.00);
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.setMode(XStream.NO_REFERENCES);
xstream.alias("product", Product.class);
System.out.println(xstream.toXML(product));
Produces:
{"product":{"name":"Banana","id":123,"price":23.0}}
To read it back in:
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.alias("product", Product.class);
Product product = (Product) xstream.fromXML(json);
System.out.println(product.getName());
Prints:
Banana
Related
Im trying to understand the procedure to do what the title says.
Im doing this in java with Gson dependency.
I am getting information from another service I use, in JSON format. So I want to get that info, put some additional info in there (like date/time) and use it afterwards for searching purposes.
The procedure is :
Get the JSON info (lets say "id") and add it to the JSON file you have
Add more info to that JSON file (lets say "Date and time of upload")
Finally, save that updated JSON file
So I read the file:
JsonReader reader = new JsonReader(new FileReader(filename));
Do I have now to convert it to string, and then update the string, so I can finally write it back to json?
If it doesn't exist, I create an empty file and then, can I update it with Json/Gson data? or do I have to create a Json File?
try {
File jsonFile = new File("C:\\uploads\\datasets");
if (jsonFile.createNewFile()){
System.out.println("File is created!");
}else{
System.out.println("File already exists.");
}
} catch (IOException e) {
e.printStackTrace();
}
Excuse any newbie/stupid mistakes I've probably made, I'm trying to understand JSON. Actually, the philosophy behind it.
JSON stands for JavaScript Object Notation and it's nothing more than a way to format data.
Taken from here:
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is
realized as an object, record, struct, dictionary, hash table, keyed
list, or associative array.
An ordered list of values. In most
languages, this is realized as an array, vector, list, or sequence.
To address your questions:
Get the JSON info (lets say "id") and add it to the JSON file you have
JsonReader reader = new JsonReader(new FileReader(inputFilename));
reader.beginArray();
reader.beginObject();
long id = -1;
while (reader.hasNext()) {
String value = reader.nextName();
if (value.equals("id")) {
id = reader.nextLong();
} else {
reader.skipValue();
}
reader.endObject();
reader.endArray();
Add more info to that JSON file (lets say "Date and time of upload")
This will get the format in YYYY.MM.DD-HH.MM.SS
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
Finally, save that updated JSON file
Create a JsonWriter.
JsonWriter writer = new JsonWriter(new FileWriter(outputFilename));
writer.beginArray();
writer.beginObject();
writer.name("id").value(id);
writer.name("timestamp").value(timestamp);
writer.endObject();
writer.endArray();
You can read more about JsonReader and JsonWriter here and here.
I'm programming an easy version of blackjack without bets in javafx, and I'm almost done with every part but now I want to be able to save and load my BlackJack game but i have no idea how to do it. Can I save everything as txt file and then load it or is there any easy way of doing it? my game layout
Consider a json serializer/deserializer like Google GSON.
Define json structure according to your data model and just serialize and deserialize your game objects to/from json file.
Example:
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
// ==> json is {"value1":1,"value2":"abc"}
// Deserialization
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
// ==> obj2 is just like obj
You can write to a file using FileOutputStream and read from a file using FileInputStream. I would use json format and have Jackson do all serialization but that's just me.
The JSON example file consists of:
{
"1st_key": "value1",
"2nd_key": "value2",
"object_keys": {
"obj_1st": "value1",
"obj_2nd": "value2",
"obj_3rd": "value3",
}
}
I read the JSON file into a String with this StringBuilder method, in order to add the newlines into the string itself. So the String looks exactly like the JSON file above.
public String getJsonContent(String fileName) {
StringBuilder result = new StringBuilder("");
File file = new File(fileName);
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
Then I translate the JSON file into an Object using MongoDB API (with DBObject, BasicDBObject and util.JSON) and I call out the Object section I need to change, which is 'object_keys':
File jsonFile = new File(C:\\example.json);
String jsonString = getJsonContent(jsonFile.getAbsolutePath());
DBObject jsonObject = (DBObject)JSON.parse(jsonString);
BasicDBObject objectKeys = (BasicDBObject) jsonObject.get("object_keys");
Now I can write new values into the Object using the PUT method like this:
objectKeys.put("obj_1st","NEW_VALUE1");
objectKeys.put("obj_2nd","NEW_VALUE2");
objectKeys.put("obj_3rd","NEW_VALUE3");
! This following part not needed, check out my answer below.
After I have changed the object, I need to write it back into the json file, so I need to translate the Object into a String. There are two methods to do this, either one works.
String newJSON = jsonObject.toString();
or
String newJSON = JSON.serialize(jsonObject);
Then I write the content back into the file using PrintWriter
PrintWriter writer = new PrintWriter(C:\\example.json)
writer.print(newJSON);
writer.close();
The problem I am facing now is that the String that is written is in a single line with no formatting whatosever. Somewhere along the way it lost all the newlines. So it basically looks like this:
{"1st_key": "value1","2nd_key": "value2","object_keys": { "obj_1st": "NEW_VALUE1","obj_2nd": "NEW_VALUE2","obj_3rd": "NEW_VALUE3", }}
I need to write the JSON file back in the same format as shown in the beginning, keeping all the tabulation, spaces etc.
Is this possible somehow ?
When you want something formatted the way you said it is addressed as writing to a file in a pretty/beautiful way. For example: Output beautiful json. A quick search on google found what i believe to solve your problem.
Solution
You're going to have to use a json parser of some sort. I personally prefer org.json and would recommend it if you are manipulating the json data, but you may also like json-io which is really good for json serialization with no external dependencies.
With json-io, it's as simple as
String formattedJson = JsonWriter.formatJson(jsonObject.toString())
With org.json, you simply pass an int to the toString method.
Thanks Saraiva, I found a surprisingly simple solution by Googling around with the words 'pretty printing JSON' and used the Google GSON library. I downloaded the .jar and added it to my project in Eclipse.
These are the new imports I needed:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
Since I already had the JSON Object (jsonObject) readily available from my previous code, I only needed to add two new lines:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String newJSON = gson.toJson(jsonObject);
Now when I use writer.print(newJSON); it will write the JSON in the right format, beautifully formatted and indented.
This may seem a little unusual, but I am looking for an efficient way to transform/map a JsonNode into a POJO.
I store some of my Model's information in json files and I have to support a couple of version of my model.
What I do is load the json file in memory in a JsonNode, apply a couple of versioning strategies to make it match the latest version of my Model.
ObjectMapper mapper = new ObjectMapper();
BufferedReader fileReader = new BufferedReader(new FileReader(projPath));
JsonNode rootNode = mapper.readTree(fileReader);
//Upgrade our file in memory
applyVersioningStrategy(rootNode);
ProjectModel project = mapJsonNodeToProject(rootNode);
Unless there's a faster way to do it, I will probably end up simply manually applying the JsonNodes to my Model
In Jackson 2.4, you can convert as follows:
MyClass newJsonNode = jsonObjectMapper.treeToValue(someJsonNode, MyClass.class);
where jsonObjectMapper is a Jackson ObjectMapper.
In older versions of Jackson, it would be
MyClass newJsonNode = jsonObjectMapper.readValue(someJsonNode, MyClass.class);
This should do the trick:
mapper.readValue(fileReader, MyClass.class);
I say should because I'm using that with a String, not a BufferedReader but it should still work.
Here's my code:
String inputString = // I grab my string here
MySessionClass sessionObject;
try {
ObjectMapper objectMapper = new ObjectMapper();
sessionObject = objectMapper.readValue(inputString, MySessionClass.class);
Here's the official documentation for that call: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)
You can also define a custom deserializer when you instantiate the ObjectMapper:
http://wiki.fasterxml.com/JacksonHowToCustomDeserializers
Edit:
I just remembered something else. If your object coming in has more properties than the POJO has and you just want to ignore the extras you'll want to set this:
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Or you'll get an error that it can't find the property to set into.
If you're using org.codehaus.jackson, this has been possible since 1.6. You can convert a JsonNode to a POJO with ObjectMapper#readValue: http://jackson.codehaus.org/1.9.4/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(org.codehaus.jackson.JsonNode, java.lang.Class)
ObjectMapper mapper = new ObjectMapper();
JsonParser jsonParser = mapper.getJsonFactory().createJsonParser("{\"foo\":\"bar\"}");
JsonNode tree = jsonParser.readValueAsTree();
// Do stuff to the tree
mapper.readValue(tree, Foo.class);
String jsonInput = "{ \"hi\": \"Assume this is the JSON\"} ";
com.fasterxml.jackson.databind.ObjectMapper mapper =
new com.fasterxml.jackson.databind.ObjectMapper();
MyClass myObject = objectMapper.readValue(jsonInput, MyClass.class);
If your JSON input in has more properties than your POJO has and you just want to ignore the extras in Jackson 2.4, you can configure your ObjectMapper as follows. This syntax is different from older Jackson versions. (If you use the wrong syntax, it will silently do nothing.)
mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
This is also a different way and can be used for an array of objects
ObjectReader reader = mapper.readerFor(new TypeReference<List<SomeClass>>() {
});
assert someJsonNode.isArray()
List<SomeClass> list = reader.readValue(someJsonNode);
this is the JSONArray:
String json = [{"1":"Kenny", "2":"Tom", "3":"Mosoti"}];
now i want to get a string array of values only eg Kenny, Tom, Mosoti
You may use any json parser to do that for instance Jackson.
It is not a good option to write your own parser as it is error-prone. Also don't re-invent the wheel.
Yeah, you should go with a mainstream library/framework like Jackson, you can read more about it here: http://wiki.fasterxml.com/JacksonInFiveMinutes
A basic example would be something like:
private static MailData unMarshallJson(String literalJson) throws JAXBException, IOException {
Data data = null;
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(literalJson, Data.class);
return data;
}
Where the Data class is a class corresponding to the parsed data, read the link that I provided for more info.