I am building a tool using java, that accesses an API.
I'm trying to let the user decide, which parameters to use (via checkboxes for instance).
So the user would decide to take one of let's say 5 parameters:
p1
p2
p3
p4
p5
and then I would make a call to the API using those parameters and receive a Json String as a response.
So that Json String can be either
{"data":[{"p1":"value1", "p2":"value2", "p3":"value3", "p4":"value4", "p5":"value5"}]}
{"data":[{"p1":"value1", "p2":"value2", "p3":"value3", "p4":"value4"}]}
{"data":[{"p1":"value1", "p2":"value2", "p3":"value3"}]}
{"data":[{"p1":"value1", "p2":"value2"}]}
or
{"data":[{"p1":"value1"}]}
I'm trying to print everything inside "data" to the console. This is the code I got so far:
JsonParser parser = new JsonParser();
JsonObject json = (JsonObject)
parser.parse(adsInsights.toString());
System.out.println(json.get("p1").getAsString() + "\t"
+ json.get("p2").getAsString() + "\t"
+ json.get("p3").getAsString() + "\t"
+ json.get("p4").getAsString() + "\t" +
json.get("p5").getAsString()
);
My problem is: how do I determine which ones to print, without doing a ton of if/elses?
All I need is every variable within "data". is there a method to do this?
EDIT:
First of all, thanks for all the answers.
For future reference I guess, this is what I did:
//getting the keys, which the user has selected. Detailed implementation irrelevant for this matter
String selectedKeys[] = getSelectedKeys();
JsonParser parser = new JsonParser();
JsonObject json = (JsonObject)
parser.parse(adsInsights.toString());
for(int i = 0; i < selectedKeys.length; i++) {
if(json.has(selectedKeys[i])) {
System.out.print(json.get(selectedKeys[i]).getAsString() + "\t");
}
}
System.out.println();
You can iterate over the Json keys no matter which keys are in it and print their values.
JsonParser parser = new JsonParser();
JsonObject json = (JsonObject)
parser.parse(adsInsights.toString());
for (key: json.keys) {
System.out.print(json.get(key).getAsString());
}
// to check if key exists or not. if not, return empty string.
private String getValues(JSONObject jsonObj, String arg) {
return jsonObj.get(arg) != null?(String) jsonObj.get(arg):"";
}
//call getValues function for every key. fetch all keys from keySet Function.
JSONObject check=(JSONObject) obj;
JSONObject data=(JSONObject) check.get("data");
Set<String> keys=data.keySet();
for(String k:keys){
System.out.println(getValues(data,k));
}
Are you building the API as well?
I think a better data structure to return from the API would be to use an array for "data", e.g.
{
"data":[
{ "id": "p1", "value": "value1" },
{ "id": "p2", "value": "value2" },
{ "id": "p3", "value": "value3" },
{ "id": "p4", "value": "value4" },
{ "id": "p5", "value": "value5" }
]
}
That way, the receiving code doesn't have to care about which items are in data, or how many. Instead it can just loop through the array and print whatever happens to be there.
Related
As the tital states above I am trying to replace the value for "name" to "abc" but that does not seem to overwrite it as it's the same value after replacing it using the Simple Json java code.
This is my java code:
String jsonString =
"{"
+ "\"data\":"
+ "["
+ "{"
+ "\"jazz\":\"black\","
+ "\"name\":\"white\","
+ "\"given\":\"red\","
+ "\"sam\":\"blue\","
+ "\"mail\":\"yellow\","
+ "\"member\":\"green\","
+ "\"department\":\"green\","
+ "\"title\":\"green\""
+ "}"
+ "]"
+ "}";
JSONParser parser = new JSONParser();
JSONObject jsonObj = (JSONObject) parser.parse(jsonString);
JSONObject newJSON = new JSONObject();
jsonObj.remove("name");
jsonObj.put("name", "abc");
As I said, the code above seems to not do anything for the "name" attribute that's already in the json structure. The output for the above looks like this:
{
"data": [
{
"given": "red",
"mail": "yellow",
"jazz": "black",
"name": "white",
"member": "green",
"department": "green",
"title": "green",
"sam": "blue"
}
],
"name": "abc"
}
What the output should look like:
{
"data": [
{
"given": "red",
"mail": "yellow",
"jazz": "black",
"name": "abc",
"member": "green",
"department": "green",
"title": "green",
"sam": "blue"
}
]
}
Any idea as to why its not changing it?
UPDATE 1
this worked for me:
JSONArray jsonArray = (JSONArray)jsonObj.get("data");
JSONObject jsonObject = ((JSONObject)(jsonArray).get(0));
jsonObject.put("name", "abc");
System.out.println(jsonObj.toJSONString());
You have the object inside you json object
You need to get the inner data object and modify it
jsonObj.get("data").put("name", "abc")
Time to time you can be faced with situations where would be perfect to replace some values in flexible way. So I'd like to show this additional approach using json-path dependency.
Specify path collection to replace real data, for example:
import static com.google.common.collect.Lists.newArrayList;
...
private static final List<String> PATHS_TO_REPLACE = newArrayList(
"$.email",
"$.colleagues.[*].email",
"$.other.required.pathmask"
);
And most important code part:
public String maskSensitiveData(String asJson) {
DocumentContext parsed = JsonPath.parse(asJson);
PATHS_TO_REPLACE.forEach(path -> parsed.set(path, "***starred***"));
return parsed.jsonString();
}
To avoid of com.jayway.jsonpath.PathNotFoundException if you sure they have to be suppressed, you can use special configuration:
private static final Configuration CONFIGURATION = Configuration
.builder()
.options(Option.SUPPRESS_EXCEPTIONS)
.build();
and parseddocument should be given in updated way:
DocumentContext parsed = JsonPath.using(CONFIGURATION).parse(asJson);
To play with code I'd recommend try prepared test for correspond service.
P.S.
If you want calculate stars for setting value (or hide only part of data) in dynamic way it also can be handled. To keep it simple for data arrays, please pay your attention on map method of the same object. Correspond example also added to the service:
public String flexibleMaskingSensitiveData(String asJson) {
DocumentContext parsed = JsonPath.using(CONFIGURATION).parse(asJson);
PATHS_TO_REPLACE.forEach(path -> parsed.map(path,
(currentValue, conf) -> starringCurrentValue(currentValue)));
return parsed.jsonString();
}
private Object starringCurrentValue(Object currentValue) {
return ofNullable(currentValue)
.filter(String.class::isInstance)
.map(String.class::cast)
.map(String::length)
.map(times -> StringUtils.repeat('*', times))
.orElse("");
}
I have an assingment to create something on the lines of a quiz. The teacher gave us all the interfaces for the Questions and the Test and even the "graphic layer" to display the quiz.
I created two classes for the Test and Question interfaces. The test class has a listArray of Questions objects along with other atributes. The Question class has the atributes you can see in the JSON File(title,score,mark,etc...).
To read the Json file i created the method "loadfromJsonFile", and it prints the file perfectly but i cant figure out how to associate each question object from the file to the arrayList.
Json File:
[
{
"type": "MultipleChoice",
"question": {
"title": "Question 1",
"score": 4,
"mark": 5,
"question_description": "The ability of an object to take on many forms is:",
"options": [
"Polymorphism",
"Encapsulation",
"Design Patter",
"Does not Exist"
],
"correct_answer": "Polymorphism"
}
},
{
"type": "MultipleChoice",
"question": {
"title": "Question 2",
"score": 4,
"mark": 5,
"question_description": "The bundling of data with the methods that operate on that data is:",
"options": [
"Polymorphism",
"Encapsulation",
"Design Patter",
"Does not Exist"
],
"correct_answer": "Encapsulation"
}
},
{
"type": "YesNo",
"question": {
"title": "Question 3",
"score": 4,
"mark": 5,
"question_description": "Object Oriented Programming is exclusive to the JAVA programming language",
"correct_answer": "no"
}
},
{
"type": "Numeric",
"question": {
"title": "Question 4",
"score": 4,
"mark": 5,
"question_description": "How many programming languages are taught in Paradigmas de Programação?",
"correct_answer": "1"
}
}]
Code for reading the Json File:
public boolean loadFromJSONFile(String s) throws TestException {
String path = "teste_A.json";
BufferedReader reader = null;
try{
reader = new BufferedReader(new FileReader(path));
JsonStreamParser p = new JsonStreamParser(reader);
JsonArray arr = (JsonArray) p.next();
for(int i=0;i<arr.size();i++){
System.out.println("--------------------------------------Question"+i+"--------------------------------------------");
JsonElement arrayElement = arr.get(i);
JsonObject obj = arrayElement.getAsJsonObject();
String type=obj.get("type").getAsString();
System.out.println("Type: " + type);
JsonObject list =obj.get("question").getAsJsonObject();
String title=list.get("title").getAsString();
System.out.println("Title: " + title);
int score=list.get("score").getAsInt();
System.out.println("Score: " + score);
int mark=list.get("mark").getAsInt();
System.out.println("Mark: " + mark);
String Description=list.get("question_description").getAsString();
System.out.println("Description: " + Description);
JsonArray opt = list.getAsJsonArray("options");
if(opt!=null){
System.out.println("Options: \n");
for (int j = 0; j < opt.size(); j++) {
JsonPrimitive value = opt.get(j).getAsJsonPrimitive();
System.out.print(" Option"+ (j+1) +": "+ value.getAsString()+ " \n");
}
System.out.println("\n");
}
String CorrectAnswer = list.get("correct_answer").getAsString();
System.out.println("Correct: " + CorrectAnswer);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
reader.close();
}catch (IOException ex){
ex.printStackTrace();
}
}
return false;
}
Here is my understanding: you can read the json file and parse the contents just fine, but the issue is how to pass the results back to the caller without returning the parameter itself. From the code snippets, the line
this.current_question = this.test.getQuestion(this.question_number);
seems like where this ArrayList will be queried in the program.
From this, I am imagining a couple of possibilites:
1) There is a setQuestion(<params>) method that you could call in the teacher's provided code.
2) There is a variable such as this.test or this.questions that you should be setting.
In either case, you would add each question inside your for loop. For example,
for(int i=0;i<arr.size();i++){
System.out.println("--------------------------------------Question"+i+"--------------------------------------------");
JsonElement arrayElement = arr.get(i);
JsonObject obj = arrayElement.getAsJsonObject();
//add obj via variable assignment
this.test.Add(obj);
//or, add obj via set method
this.test.setQuestion(i, obj); //or whatever parameters are needed :)
EDIT:
Because your Question class extends IQuestion, you can cast an instance of the Question class to IQuestion. Plus, the Question class is using a Gson library to deserialize for you, which means you saved yourself some legwork. (yay!)
for(int i=0;i<arr.size();i++){
//get the whole json array element
JsonElement arrayElement = arr.get(i);
//...
//get question object
JsonObject list = obj.get("question").getAsJsonObject();
//cast to IQuestion using the Question class Gson deserializer
IQuestion q = new Gson().fromJson(list, Question.class);
//And, add using built in method
this.test.setQuestion(q);
This website has some examples of Gson deserialization, one of which I used up above.
EDIT:
After adding a constructor to the Question class, the code to add a question of specific types will need type casting.
for(int i=0;i<arr.size();i++){
//get the whole json array element
JsonElement arrayElement = arr.get(i);
//...
//get question object
JsonObject list = obj.get("question").getAsJsonObject();
//cast question to correct interface based on question type
if (type=="Multiple Choice") {
IQuestionMultipleChoice questionMP = (IQuestionMultipleChoice) new Question(<params>);
this.test.setQuestion(questionMP);
} else if(type=="Yes/No") {
//...
*I am already getting this JSON object from responce.body(). I want every data inside this separately in variable. I am using java.
{
"Classes":{
"Primary":{
"Classes":{
"1":{
"section":[
"a",
"b"
]
},
"2":{
"sections":[
"a",
"b"
]
}
}
}
}
}
*I know how to get the JSONObject but i dont know how can i get that array inside "section". even if i get that array with JSONArray then how to convert it to JSONObject? or String.
*Note that inside value of "section" array is dynamic, value inside that array is dynamic and can be multiiple from "a" to "z". Also JSONObject inside "Classes"(inside primary) is also dynamic. there can be dynamic and multiple "1","2"... and it is string, It is not necessary that there will be incremental numbers.
After 30 mins of war, I find out your answer just copy this code and paste where you want to use -
Here it is -
String json = "{
"Classes": {
"Primary": {
"Classes": {
"1": {
"section": [
"a",
"b"
]
},
"2": {
"sections": [
"a",
"b"
]
}
}
}
}
}";
try {
JSONObject jsonObject = new JSONObject(json);
Log.d("jsonObj", jsonObject.toString());
JSONObject classJsonObj = jsonObject.optJSONObject("Classes");
JSONObject primaryJsonObj = classJsonObj.optJSONObject("Primary");
JSONObject internalClassJsonObj = primaryJsonObj.optJSONObject("Classes");
if(internalClassJsonObj != null){
int i = 1;
JSONObject dynmaicInternalJsonObj = null;
while (true){
dynmaicInternalJsonObj = internalClassJsonObj.optJSONObject(i+"");
if(dynmaicInternalJsonObj != null){
JSONArray sectionJsonArr = dynmaicInternalJsonObj.optJSONArray("sections");
Log.d("SectionArr", sectionJsonArr.toString());
// Finally you got your section data here...
if(sectionJsonArr != null){
for(int j=0; j<sectionJsonArr.length(); j++){
System.out.println("Dynamic Sections Data is: - " + sectionJsonArr.opt(j));
}
System.out.println("\n\n");
}
}else{
break;
}
i++;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
You've tagged this as java so I can only assume you want a solution for that language.
To use this data it needs to parsed, this means you are converting the data into a more usable type.
Click this to learn how to parse JSON in java
Assuming you need solution in java, use this to get a object classes for your json structure and then convert your json to java objects using libraries like GSON.
Example:
String json = "{\"city\":\"San Jose\", \"state\": \"CA\", \"country\":\"USA\"}";
Gson gson = new Gson();
Place place = gson.fromJson(json, Place.class);
If you are using ionic (typescript or javascript), you can use the below approach
var json = "{
"Classes": {
"Primary": {
"Classes": {
"1": {
"section": [
"a",
"b"
]
},
"2": {
"sections": [
"a",
"b"
]
}
}
}
}
}";
for(let item in json.Classes.Primary.Classes){
console.log(item.sections);
}
If you want to display the same data in frontend using html, use *ngFor
<div *ngFor="let item in json.Classes.Primary.Classes ">
<h5>{{item.sections}}</h5>
</div>
I hope it helps.
Currently working on an android app and I need help on how I can go about extracting the subfields within the responses field of this json object:
Currently I am doing the following to extract some of the other fields:
JSONObject json = new JSONObject(response2);
int id = json.getInt("id");
String desc = json.getString("description");
JSONObject json2 = json.getJSONObject("owner");
String username = json2.getString("userName");
You need to create logic to parse the data. Every item from the JSON string is in the JSONObject you created with
JSONObject json = new JSONObject(response2);
You're on the right track with what you're doing. Just use the corresponding methods available in JSONObject and JSONArray classes to move through the object.
Start with the main object
{ // <-- this is your main object (AKA JSONObject json = new JSONObject(response2))
"id": 1, // to pull this id use json.getInt("id");
"title": "some text here", // to pull this title use json.getString("title");
...
"owner": { // Here's the logic part, owner is itself, a JSON object. so now you must extract it and parse through it.
// to pull the "owner" JSON object, use JSONObject ownerObject = json.getJSONObject("owner");
"userId": 1, // Now use the ownerObject to pull it's values. ownerObject.getInt("userId");
"userName": "TestingUser", // to pull this userName use ownerObject.getString("userName");
...
}
...
}
If it's an array, for example:
"someJSONArray": [{ "id": 1, "userName": "TestingUser1" }, { "id": 2, "userName": "TestingUser2" }]
then you would call:
JSONArray someJSONArray = getJSONArray("someJSONArray");
// Get each object from the array.
JSONObject object1 = someJSONArray.getJSONObject(0);
JSONObject object2 = someJSONArray.getJSONObject(1);
or if the array contains a string, for example:
"someKey": [ 23, 435, 123, 6345, 123 ]
then you would call:
JSONArray someKeyArray = getJSONArray("someKey");
for (int i = 0; i < someKeyArray.length(); i++) {
// Extract the value.
int itemValue = someKeyArray.getInt(i);
}
The data is there, you just have to parse it.
In java, I am trying to parse values from this json..
[
{
"2012-01-02": {
"age": 3,
"dob": "2010-01-03",
"name": "jack"
},
"2012-01-03": {
"age": 3,
"dob": "2010-01-04",
"name": "jill"
},
"2012-01-04": {
"age": 3,
"dob": "2010-01-05",
"name": "john"
},
"2012-01-05": {
"age": 3,
"dob": "2010-01-06",
"name": "miran"
}
}
]
Using JSONObject, I was trying to get the value of just "age" and then add them up to do some data manipulation.
I created a JSONObject
Created an iterator and then stored them to a map
This gets me the inner element like:
{
"age": 3,
"dob": "2010-01-06",
"name": "miran"
}
After this, not sure how to extract just age from each element. Do i create another jsonobject and pass this new string, extract age out of it or is there a better way to do this? (I am sure there is one)
UPDATE:
This is what I currently have that gives me {"age":3,"dob":"2012-01-06","name":"miran"}
JSONObject jsonobj = new JSONObject();
try {
jsonobj = new JSONObject(pastweekVol);
Iterator iter = jsonobj.keys();
Map<String, String> map = new HashMap<String, String>();
while(iter.hasNext()){
String jsonkey = (String)iter.next();
String value = jsonobj.getString(jsonkey);
logger.debug("first pass value is: {}", value);
} catch (JSONException je) {
logger.debug("exception is: {}",je);
}
I was thinking that since I am getting {"age":3,"dob":"2012-01-06","name":"miran"}, I would create another json object and pass in this string, which will give me value of "age". The problem here is that I get repetitive values. Of course, something very basic is missing here but I can't seem to figure that out.
If you have the inner element as a JSONObject instance - say person - then you can directly access the age:
int age = person.getInt("age");
and do something with it:
sum += age;
You might consider a library like Google's GSON (http://code.google.com/p/google-gson/) if you want to be able to easily parse arbitrarily complex JSON strnigs into generic objects.
Using org.json is probably not your best bet -- this API has many flaws. Using Jackson, you can easily extract age from each member value:
ObjectMapper mapper = new ObjectMapper();
JsonNode fullDocument = mapper.readTree(xxx); // xxx can be many things
// Not an object? Bail out
if (!fullDocument.isObject())
throw new IllegalArgumentException("not an object");
// This will iterate through object values
for (JsonNode value: fullDocument)
// do something with value.get("age")
// in particular, you can test for .isIntegralNumber()