I am trying to deserialize the following string, I am somewhat new to java and I cannot get this to work for the life of me... I am only trying to decode two strings in the object for now. My JSON and Java classes below. I am getting the result variable ok.
{
"result": "true",
"recentlyMarkedTerritories": {
"0": {
"pk_activity": "471",
"fk_activity_type": "100",
"activity_content": "Hhhhh",
"fk_user": "2",
"activity_image": "2_QZe73f4t8s3R1317230457.jpg",
"created": "1317244857",
"activity_status": "1",
"activity_location_lat": "43.515283",
"activity_location_lon": "-79.880678",
"fk_walk": null,
"fk_event_location": "73",
"user_point": "0",
"public_image": "0",
"fk_event_location_lat": "43.515273",
"fk_event_location_lon": "-79.879989",
"profile_image": "2_y9JlkI3CZDml1312492743.jpg",
"user_gender": "1",
"user_dob": "236073600",
"user_nickname": "junoman",
"isFriend": "false",
"profile_image_thumb": "2_y9JlkI3CZDml1312492743_t.jpg",
"activity_image_thumb": "2_QZe73f4t8s3R1317230457_t.jpg",
"relationship_status_idx": "2",
"isBlocked": "false"
},
"1": {
"pk_activity": "469",
"fk_activity_type": "100",
"activity_content": "Jsjsjs",
"fk_user": "1",
"activity_image": null,
"created": "1317244508",
"activity_status": "1",
"activity_location_lat": "43.515283",
"activity_location_lon": "-79.880678",
"fk_walk": null,
"fk_event_location": "73",
"user_point": "0",
"public_image": "0",
"fk_event_location_lat": "43.515273",
"fk_event_location_lon": "-79.879989",
"profile_image": "1_4Cpkofueqnrb1316895161.jpg",
"user_gender": "1",
"user_dob": "116841600",
"user_nickname": "JoePennington",
"isFriend": "false",
"profile_image_thumb": "1_4Cpkofueqnrb1316895161_t.jpg",
"activity_image_thumb": null,
"relationship_status_idx": "1",
"isBlocked": "false"
},
.....
}
}
And my java class below
RecentActivity infoList = null;
Gson gson = new Gson();
infoList = gson.fromJson(JSONString, RecentActivity.class);
public class RecentActivity {
String result;
recentlyMarkedTerritories recentlyMarkedTerritories = null;
public RecentActivity() {
}
public class recentlyMarkedTerritories {
public Set<recentlyMarkedTerritories> pk_activity = new HashSet<recentlyMarkedTerritories>() ;
public recentlyMarkedTerritories() { }
}
}
Please forgive my lack of description but I'm sure the code helps. The JSON is already used in other applications so changing it is not an option.. :(
Thanks!
Here are some nice Tutorials for JSON that will help you out.
GSON
JSON
JSON Example with source code
UPDATED
Try like this,
try {
JSONObject object = new JSONObject(jsonString);
JSONObject myObject = object.getJSONObject("recentlyMarkedTerritories");
for (int i = 0; i < object.length(); i++) {
JSONObject myObject2 = myObject.getJSONObject(Integer.toString(i));
System.out.println(myObject2.toString(2));
}
} catch (Exception e) {
e.printStackTrace();
}
I am not sure of the gson code to write, but the structure of your json looks more like the following java representation (though you might want booleans and ints instead of String fields):
public class RecentActivity {
String result;
Map<String,RecentlyMarkedTerritory> recentlyMarkedTerritories = null;
}
public class RecentlyMarkedTerritory {
String pk_activity;
// other fields
}
Related
i'm trying to add new data to existing json file that named question.json but it's not working! it create a new file, can someone help me please!
mycode: i'm using json-simple1.1
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class Main {
public static void writeToJson() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("question", "q3");
ArrayList<String>anss = new ArrayList<>();
anss.add("a1");
anss.add("a2");
anss.add("a3");
anss.add("a4");
JSONArray arr = new JSONArray();
arr.add(anss.get(0));
arr.add(anss.get(1));
arr.add(anss.get(2));
arr.add(anss.get(3));
jsonObject.put("answers",arr);
jsonObject.put("correct_ans", "2");
jsonObject.put("level", "2");
jsonObject.put("team", "animal");
try {
FileWriter file = new FileWriter("json/quetion.json");
file.write(jsonObject.toJSONString());
file.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[]args) {
writeToJson();
}
}
{
"questions":[
{
"question": "q1",
"answers": [
"answer1",
"answer2",
"answer3",
"answer4"
],
"correct_ans": "2",
"level": "1",
"team": "animal"
},
{
"question": "q2",
"answers": [
"answer1",
"answer2",
"answer3",
"answer4"
],
"correct_ans": "1",
"level": "2",
"team": "animal"
}
]
}
this is the json file i want to add what i wrote in the code to this json file but i failed! i need someone to tell me how can i add a new json object like {"question" : "q2" ...} without changing the format of the json file or creating a new json file.
org.json.simple
The structure of your JSON has more levels of nesting than can be observed in your code therefore your result doesn't match.
That's what you have in the JSON:
JSONObject { field : JSONArray [ JSONObject { field : value, field : JSONArray, ... }
I.e. JSONObject which contains a JSONArray which might contain several JSONObjects which in turn contain a JSONArray.
That's how it can be translated into the code (to avoid redundancy logic which for creating a nested JSONObject was extracted into a separate method):
JSONObject root = new JSONObject();
JSONArray questions = new JSONArray();
JSONObject question1 = createQuestion(
"q1", "2", "1", "animal",
"answer1", "answer2", "answer3", "answer4"
);
JSONObject question2 = createQuestion(
"q2", "1", "2", "animal",
"answer1", "answer2", "answer3", "answer4"
);
Collections.addAll(questions, question1, question2);
root.put("questions", questions);
public static JSONObject createQuestion(String questionId,
String correctAnswer,
String level, String team,
String... answers) {
JSONObject question = new JSONObject();
question.put("question", questionId);
JSONArray answersArray = new JSONArray();
Collections.addAll(answersArray, answers);
question.put("answers", answersArray);
question.put("correct_ans", correctAnswer);
question.put("level", level);
question.put("team", team);
return question;
}
That's it.
There's a lot of low-level logic which you can eliminate if you would choose a more mature tool for parsing JSON like Jackson, Gson.
Jackson
Here's an example using Jackson library.
Firstly, let's create two POJO: one representing a single question and another wrapping a list of question. For convince, and also in order to avoid posting boilerplate code, I would use Lombock's.
Question class:
#Builder
#AllArgsConstructor
#Getter
public static class Question {
private String questionId;
private List<String> answers;
private String correctAnswer;
private String level;
private String team;
}
Questions class:
#AllArgsConstructor
#Getter
public static class Questions {
private List<Question> questions;
}
Here's how such objects can be serialized:
Question question3 = Question.builder()
.questionId("q1")
.answers(List.of("answer1", "answer2", "answer3", "answer4"))
.correctAnswer("2")
.level("1")
.team("animal")
.build();
Question question4 = Question.builder()
.questionId("q2")
.answers(List.of("answer1", "answer2", "answer3", "answer4"))
.correctAnswer("1")
.level("2")
.team("animal")
.build();
Questions questions1 = new Questions(List.of(question3, question4));
ObjectMapper mapper = new ObjectMapper();
String json1 = mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(questions1);
System.out.println(json1);
Output:
{
"questions" : [ {
"questionId" : "q1",
"answers" : [ "answer1", "answer2", "answer3", "answer4" ],
"correctAnswer" : "2",
"level" : "1",
"team" : "animal"
}, {
"questionId" : "q2",
"answers" : [ "answer1", "answer2", "answer3", "answer4" ],
"correctAnswer" : "1",
"level" : "2",
"team" : "animal"
} ]
}
I have data that looks like this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"data": {
"lib": {
"files": [
"data1",
"data2",
"data3",
"data4"
],
"another file": [
"file.jar",
"lib.jar"
],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
Here is the function I'm using to prettify the JSON data:
public static String stringify(Object o, int space) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I am using the Jackson JSON Processor to format JSON data into a String.
For some reason the JSON format is not in the format that I need. When passing the data to that function, the format I'm getting is this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"another data": {
"lib": {
"files": [ "data1", "data2", "data3", "data4" ],
"another file": [ "file.jar", "lib.jar" ],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
As you can see under the "another data" object, the arrays are displayed as one whole line instead of a new line for each item in the array. I'm not sure how to modify my stringify function for it to format the JSON data correctly.
You should check how DefaultPrettyPrinter looks like. Really interesting in this class is the _arrayIndenter property. The default value for this property is FixedSpaceIndenter class. You should change it with Lf2SpacesIndenter class.
Your method should looks like this:
public static String stringify(Object o) {
try {
ObjectMapper mapper = new ObjectMapper();
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentArraysWith(new Lf2SpacesIndenter());
return mapper.writer(printer).writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I don't have enough reputation to add the comment, but referring to the above answer Lf2SpacesIndenter is removed from the newer Jackson's API (2.7 and up), so instead use:
printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
Source of the solution
I have a JSON with list of Objects and any of the item in the list can have null or the same object as a value for a key. I am looking for a faster way to parse the json to arrive at my final result.
The data structure looks like -
[
{
"firstName": "Bruce",
"familyMembers": null
},
{
"firstName": "Gates Family",
"familyMembers": [
{
"firstName": "Bill",
"familyMembers": null
},
{
"firstName": "Steve",
"familyMembers": null
}
]
},
{
"firstName": "Lee",
"familyMembers": null
},
{
"firstName": "Chan",
"familyMembers": null
}
]
The output should be a set = ("Bruce", "Bill", "Steve", "Lee", "Chan").
I am looking for a best possible way to do this in Java, such that i dont increase my response time by getting caught in this parsing hell.
Appreciate your time on this.
Try my recursive implementation.
public static void jsonArrayToSet(JSONArray jAry, Set<String> result, String targetKey, String subArrayKey, boolean includeNode){
try {
for (int i = 0; i < jAry.length(); i++) {
JSONObject jObj = jAry.getJSONObject(i);
boolean hasSubArray = false;
JSONArray subArray = null;
if(jObj.has(subArrayKey)){
Object possibleSubArray = jObj.get(subArrayKey);
if(possibleSubArray instanceof JSONArray){
hasSubArray = true;
subArray = (JSONArray) possibleSubArray;
}
}
if(hasSubArray){
if(includeNode){
result.add(jObj.getString(targetKey));
}
jsonArrayToSet(subArray, result, targetKey, subArrayKey, includeNode);
} else {
result.add(jObj.getString(targetKey));
}
}
} catch (JSONException e){
e.printStackTrace();
}
}
jAry: The source JSONArray.
result: The Set you want to write in.
targetKey: The key that maps to an entry which you want to add to result.
subArrayKey: The key that map to a sub-JSONArray.
includeNode: When current JSONOnject is a node containing sub-array, add it to result or not.
In your case, you can call:
jsonArrayToSet(yourJsonArray, yourSet, "firstName", "familyMembers", false);
As mentioned in my comment.
Your first issue would be the content in your JSON file. Based on the standard, it should be wrapped around with a set of { }.
Example
{
"members": [
{
"firstName": "Bruce",
"familyMembers": null
},
{
"firstName": "Gates Family",
"familyMembers": [
{
"firstName": "Bill",
"familyMembers": null
},
{
"firstName": "Steve",
"familyMembers": null
}
]
},
{
"firstName": "Lee",
"familyMembers": null
},
{
"firstName": "Chan",
"familyMembers": null
}
]
}
Also, I think the value "Gates Family" should be part of the output? Since it is under the "FirstName" attribute.
Anyway, here is my solution that is based on the org.json library. It also uses Goggle's GSon library where I use it for reading the JSON file.
import org.json.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
public class solution {
public static final String JSON_DATA_FILE_PATH = "./data/source_37848106.json";
private static boolean hasMoreFamilyName(JSONObject json) {
return json.has("familyMembers") && json.get("familyMembers") != JSONObject.NULL;
}
private static void trackFirstName(Map<String, Integer> nameTracker, JSONObject json) {
if (!nameTracker.containsKey(json.getString("firstName"))) {
nameTracker.put(json.getString("firstName"), /*DUMMY VALUE =*/1);
}
}
private static void getNames(Map<String,Integer> nameTracker, JSONArray jsonArr) {
for (int i = 0; i< jsonArr.length(); i++) {
JSONObject item = jsonArr.getJSONObject(i);
if (hasMoreFamilyName(item)) {
getNames(nameTracker, item.getJSONArray("familyMembers"));
}
trackFirstName(nameTracker, item);
}
}
public static void main(String[] args) {
Map<String, Integer> nameTracker = new HashMap<>();
try {
String text = Files.toString(new File(JSON_DATA_FILE_PATH), Charsets.UTF_8);
JSONObject json = new JSONObject(text);
getNames(nameTracker, json.getJSONArray("members"));
}
catch (Exception ex) {
System.out.println("Something is wrong.");
}
for (Map.Entry<String,Integer> entry : nameTracker.entrySet()) {
System.out.println(entry.getKey());
}
}
You can use ObjectMapper defined in jackson-databind-2.6.5.jar
Define a java class with fields similar to json pattern and then just bind them like:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
Family family=objectMapper.readValue(jsonString, Family.class);
Now you will have a java object similar to your json string pattern and you can print it the way you like.
String jsonResponse=Utils.getGsonInstance().toJson(Object);
jsonResponse returns :
[
{
"Key":"1",
"Code": "11",
},
{
"key":"2",
"code": "22",
}
]
End result I am looking for is to wrap this JSON-String in another Key E.g.
{
"MainObj":
[
{
"Key":"1",
"Code": "11",
},
{
"key":"2",
"code": "22",
}
]
}
Is there a way I can achieve this using GSON Api ?
I tried ::
JSONObject jsonObject = new JSONObject();
jsonObject.put("MainObj",jsonResponse);
Output I am getting is :
{"MainObj": "[{\"Key\":\"1",\"Code\":\"11\"}, {\"Key\":\"2",\"Code\":\"22\"}]"}
Continue with GSON like :
public class MainObj {
#SerializedName("MainObj")
public List<Key> Main;
public class Key {
#SerializedName("Key")
public String Key;
#SerializedName("code")
public String Code;
}
}
And change
JSONObject jsonObject = new JSONObject();
jsonObject.put("MainObj",jsonResponse);
by
String tmp = new Gson().toJson(new MainObj());
Can somebody help me with Gson parser. When I remove change from JSON and Result it works fine but with change it throws JsonParseException-Parse failed.
Result[] response = gson.fromJson(fileData.toString(), Result[].class);
I have classes like this
public class Result {
public String start_time;
public String end_time;
public change[] change;
}
and
public class change {
public String id;
public String name;
}
and Json string like
[
{
"start_time": "8:00",
"end_time": "10:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
},
{
"start_time": "9:00",
"end_time": "15:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
}
]
Can somebody tell me what I did wrong ? Any idea why it won't work with array ?
As has been suggested, you need to use a list instead. Gson has pretty good documentation for using parametized types with the parser, you can read more about it here. Your code will end up looking like this:
Type listType = new TypeToken<List<Result>>() {}.getType();
List<Result> results = gson.fromJson(reader, listType);
for (Result r : results) {
System.out.println(r);
}