Display json data nicely from web api? - java

I created an app which pulls json data from an online web api and displays the text of that json data in textview. however, it shows as the raw json data - I would like to take out all the symbols and just display the text in a nice way.
What is this process called please?
Example of json string:
{
"Title": "Up",
"Year": "2009",
"Rated": "PG",
"Released": "29 May 2009",
"Runtime": "96 min",
"Genre": "Animation, Adventure, Comedy",
"Director": "Pete Docter, Bob Peterson",
"Writer": "Pete Docter (story), Bob Peterson (story), Tom McCarthy (story), Bob Peterson (screenplay), Pete Docter (screenplay)",
"Actors": "Edward Asner, Christopher Plummer, Jordan Nagai, Bob Peterson",
"Plot": "Seventy-eight year old Carl Fredricksen travels to Paradise Falls in his home equipped with balloons, inadvertently taking a young stowaway.",
"Language": "English",
"Country": "USA",
"Awards": "Won 2 Oscars. Another 69 wins & 69 nominations.",
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTk3NDE2NzI4NF5BMl5BanBnXkFtZTgwNzE1MzEyMTE#._V1_SX300.jpg",
"Metascore": "88",
"imdbRating": "8.3",
"imdbVotes": "600,265",
"imdbID": "tt1049413",
"Type": "movie",
"Response": "True"
}

You need FastJson.
Step 0.
Import Fastjson into your project.
0.1 - Android Studio Gradle
compile 'com.alibaba:fastjson:1.2.7'
0.2 - Eclipse
Add library
http://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.7/fastjson-1.2.7.jar
Step 1.
Creat Java Objects like
public class MyJsonBean {
private String Title;
private String Year;
private String Rated;
//...
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getYear() {
return Year;
}
public void setYear(String year) {
Year = year;
}
public String getRated() {
return Rated;
}
public void setRated(String rated) {
Rated = rated;
}
//....
}
Step 2.
String jsonStr = "Your Json Str";
MyJsonBean myBean = JSON.parseObject(jsonStr, MyJsonBean.class);
System.out.println("Title = " + myBean.getTitle());
System.out.println("Year = " + myBean.getYear());
System.out.println("Rated = " + myBean.getRated());
Step 3.
You can use myBean.getName() to get value.
Then, it's done.
Ps. this website can help you create Java Objects
http://www.jsonschema2pojo.org/
Click Preview

You have to parse the Raw Json data into a String or you can user Gson libraries to convert Json object to Java Object.
If your Json is like
{
"text" : "value"
}
Then create a class
public class Text
{
public String text;
}
Then parse json using Gson object.
Gson gson = new Gson();
Text parsedText = gson.fromJson(jsonString,
Text.class);
Now set parsedText.text to your textview
Regards,
Sree

What you need is a JSON consumer, which this article covers (and provides source to): https://www.nabisoft.com/tutorials/java-ee/producing-and-consuming-json-or-xml-in-java-rest-services-with-jersey-and-jackson
A JSON consumer simply makes it easier for you to manage key:value pairs and (obviously) print them out. You direct the consumer to read the incoming data and it parses it into a handy object map for you to access.
This is even nicer in Groovy, but I know you wanted a pure Java solution.

you should parse your json string with this class JSONObject like this:
you have a string object jsonString with this content:{"Title":"Up","Year":"2009","Rated":"PG","Released":"29 May 2009","Runtime":"96 min","Genre":"Animation, Adventure, Comedy","Director":"Pete Docter, Bob Peterson","Writer":"Pete Docter (story), Bob Peterson (story), Tom McCarthy (story), Bob Peterson (screenplay), Pete Docter (screenplay)","Actors":"Edward Asner, Christopher Plummer, Jordan Nagai, Bob Peterson","Plot":"Seventy-eight year old Carl Fredricksen travels to Paradise Falls in his home equipped with balloons, inadvertently taking a young stowaway.","Language":"English","Country":"USA","Awards":"Won 2 Oscars. Another 69 wins & 69 nominations.","Metascore":"88","imdbRating":"8.3","imdbVotes":"600,265","imdbID":"tt1049413","Type":"movie","Response":"True"}
try {
//parse string
JSONObject jso = new JSONObject(jsonString);
//get data
String title = jso.getString("Title");
int year = jso.getInt("Year");
...
}catch(JSONException e) { e.printStackTrace(); }

You don't particularly need to create a custom class to parse the JSON using GSON.
You can pass it as a JsonObject and easily parse it from that.
Gson gson = new Gson();
JsonObject obj = gson.fromJson(JSON_DOCUMENT, JsonObject.class);
String title = obj.get("Title").getAsString();
String rated = obj.get("Rated").getAsString();
You can even grab JSON nested arrays and grab elements from them.
obj.get("SomeArray").getAsJsonArray();
Hope this helps :)

Related

Getting string from JSON response in Java

Can't figure out how to get string of JSON response. From OpenWeatherMap API ( https://samples.openweathermap.org/data/2.5/forecast?id=524901&appid=b6907d289e10d714a6e88b30761fae22 ) want to get the first temp_min and temp_max.
I have tried to post the JSON response in a JSON formatter and go through it logically but that didn't help me much. Tried different solutions throughout google.
The last try from my side is this:
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("list");
JSONObject firstObject = (JSONObject)array.get(0);
String tempmax = firstObject.getJSONObject("main").getString("temp_max");
String tempmin = firstObject.getJSONObject("main").getString("temp_min");
From the following API response, I want to receive temp_min and temp_max:
{
"cod":"200",
"message":0.0032,
"cnt":36,
"list":[
{
"dt":1487246400,
"main":{
"temp":286.67,
"temp_min":281.556,
"temp_max":286.67,
"pressure":972.73,
"sea_level":1046.46,
"grnd_level":972.73,
"humidity":75,
"temp_kf":5.11
},
"weather":[ ],
"clouds":{ },
"wind":{ },
"sys":{ },
"dt_txt":"2017-02-16 12:00:00"
},
[..]
I expect to get the temp_min and temp_max values from API response, but at the moment it's just empty.
I have just checked your code using this library with newest version. I loaded json content from local file and I had to change the way you read values of temperature :
public static void main(String[] args) throws IOException {
String collect = Files.lines(Paths.get("src/main/resources/waether.json")).collect(Collectors.joining());
JSONObject jsonObject = new JSONObject(collect);
JSONArray array = jsonObject.getJSONArray("list");
JSONObject firstObject = (JSONObject)array.get(0);
double tempmax = firstObject.getJSONObject("main").getDouble("temp_max");
double tempmin = firstObject.getJSONObject("main").getDouble("temp_min");
System.out.println("Temp min " + tempmin);
System.out.println("Temp max " + tempmax);
}
The output is :
Temp min 259.086
Temp max 261.45
As you see I had to use getDouble methods as those values were not json strings - they were numbers. I am not sure which version of this library you are using but with newest version it works.
Big thanks to michalk and others for help. Edited michalk's answer a bit, so it meets my project and it solved the problem I was having.

Parsing JSON double brackets with Java

I'm having some trouble as I've hit a roadblock in learning how to parse JSON with json simple.
To make myself concise;
I am trying to parse this bit of JSON from a url
"hourly": {
"summary": "Clear throughout the day.",
"icon": "clear-day",
"data": [
{
"time": 1550379600,
"summary": "Clear",
"icon": "clear-day",
"precipIntensity": 0,
"precipProbability": 0,
"temperature": 20.18,
"apparentTemperature": 14.31,
"dewPoint": 13.79,
"humidity": 0.76,
"pressure": 1024.47,
"windSpeed": 4.08,
"windGust": 5.25,
"windBearing": 30,
"cloudCover": 0.07,
"uvIndex": 0,
"visibility": 10,
"ozone": 342.67
}
so, in using json simple, this is how I am parsing this JSON
try{
String genreJson = IOUtils.toString(new URL(url));
JSONObject genreJsonObject = (JSONObject) JSONValue.parseWithException(genreJson);
//get the title
System.out.println(genreJsonObject.get("hourly")); //THIS WORKS
//System.out.println(genreJsonObject.get("visibility"));
//get the data
JSONArray genreArray = (JSONArray) genreJsonObject.get(0);
//get the first genre
//JSONObject firstGenre = (JSONObject) genreArray.get(0);
//System.out.println(firstGenre.get("data"));
}
catch (IOException | ParseException e){
e.printStackTrace();
}
So, in calling System.out.println(genreJsonObject.get("hourly")); I get everything within the brackets titled "hourly". My intent is to parse for the data within the "hourly" bracket, although I can't figure out how to parse for a title within a titled bracket. Specifically, I need the time, the precipProbability, precipIntensity, and precipProbability (this attribute is not in the example).
I apologize for any lack of detail as I'm doing this as part my first hackathon, and I'm trying not to fall asleep right now.
I greatly appreciate anyone's help.
This is object to describe your json "data" part:
class Data {
private Long time;
private String summary;
private String icon;
private Double dewPoint;
// add all the fields you need
// add empty constructor + getters and setters
}
if you want to skip some of the fields in "data" which you don't care about use
#JsonIgnoreProperties(ignoreUnknown = true)
class Data{
...
}
Your parent object is "hourly", so:
class Hourly {
private String summary;
private String icon;
private List<Data> data;
// add all the fields you need
// add empty constructor + getters and setters
}
At this point the Java POJO classes describe the Json data, so you're ready to map the JSON to the Java classes.
To read this with Jackson, you will need the String representation of the Json (without any URL parts), so let's assume you can do that in a string called "inputJsonString".
Reading this with Jackson will be as simple as:
ObjectMapper mapper = new ObjectMapper();
Hourly hourly = mapper.readValue(inputJsonString, Hourly.class);

Java creating an api to expose a csv instead of json

I am working on a Java api - using Spring Boot - I would like to create a controller that exports data from the db - into a csv that a user can download.
This is an example of what I have making Json responses.
// get chart
#SuppressWarnings("unchecked")
public Object getChart() {
// build clean object
JSONObject contents = new JSONObject();
//inverse bubble chart
JSONObject chart = new JSONObject();
chart.put("label", "250 applicants");
chart.put("value", 120);
contents.put("chart", chart);
contents.put("number", "0202 000 000");
JSONObject json = new JSONObject();
json.put("contents", contents);
return json;
}
I've seen this example -- but its being called from a reactjs framework - so not sure how I would fetch the HttpServletResponse?
Create and Download CSV file Java(Servlet)
would I invoke the api as usual?
//api/getMyCsv
#SuppressWarnings("unchecked")
#RequestMapping(value = {"/api/getMyC"}, method = RequestMethod.GET)
#CrossOrigin(origins = {"*"})
public ResponseEntity<?> getHome(
//HttpServletRequest request
) throws Exception {
JSONObject chart = getChart();
JSONArray data = new JSONArray();
data.add(chart);
//create empty response
JSONObject response = new JSONObject();
//create success response
response.put("data", data);
response.put("status", "success");
response.put("msg", "fetched csv");
return new ResponseEntity<>(response, HttpStatus.OK);
}
so with the react - using axios
export function fetchCsv(data) {
let url = "http://www.example.com/api/getMyC";
return function (dispatch) {
axios.get(url, {
params: data
})
.then(function (response) {
response = response.data.data;
dispatch(alertSuccess(response));
})
.catch(function (error) {
dispatch(alertFail(error));
});
}
}
CSV is just comma separated values right?
So, you can represent a row of data for example, as a class.
Take an address:
30 my street, my town, my country
if I wanted to represent that data as a class, and later as CSV data I'd make a class something like this:
public class AddressCSV{
private String street;
private String town;
private String country;
public AddressCSV(String street, String town, String country){
this.street = street;
this.town = town;
this.country = country;
}
// getters and setters here
// here you could have a method called generateCSV() for example
// or you could override the toString() method like this
#Override
public String toString(){
return street + "," + town + "," + country + "\n"; // Add the '\n' if you need a new line
}
}
Then you use it the same way as your JSONObject, except instead of returning the whole object you do return address.toString();
This is a very simple example of course. Checkout the StringBuilder class if your have a lot of things to build.
Overriding the toString() method means you can do things like pass your object like System.out.printline(address) and it will print the CSV.
The Spring way to help (un)marshaling data is to implement and register an HttpMessageConverter.
You could implement one that specifically handles MediaType text/csv, and supports whatever object types you decide to implement, e.g.
List<List<?>> - Row is a list of values, auto-converted to string.
List<Object[]> - Row is an array of values, auto-converted to string.
List<String[]> - Row is an array of string values.
List<?> - Row is an bean object, field names added as header row.
You may even implement your own field annotations to control column order and header row values.
You could also make it understand JAXB and/or JSON annotations.
With such a converter in place, it's now easy to write Controller methods returning CSV:
#GetMapping(path="/api/getMyC", produces="text/csv")
public List<String[]> getMyCAsCsv() {
List<Object[]> csv = Arrays.asList(
new Object[] { "First Name", "Last Name", "Age" },
new Object[] { "John" , "Doe" , 33 },
new Object[] { "Jane" , "Smith" , 29 }
);
return csv;
}
DO NOT try doing basic String trickery because the address, especially the street is bound to contain characters such as commas, quotes or line endings. This can easily mess up the CSV output. These characters need to be properly escaped in order to generate a parseable CSV output. Use a CSV library for that instead.
Example with univocity-parsers:
ResultSet rs = queryDataFromYourDb();
StringWriter output = new StringWriter(); //writing to a String to make things easy
CsvRoutines csvRoutine = new CsvRoutines();
csvRoutine.write(rs, output);
System.out.println(output.toString());
For performance, can write to an OutputStream directly and add more stuff to it after dumping your ResultSet into CSV. In such case you will want to keep the output open for writing. In this case call:
csvRoutine.setKeepResourcesOpen(true);
Before writing the ResultSet. You'll have to close the resultSet after writing.
Disclaimer: I'm the author of this library. It's open-source and free.

Serializing List<Item> to JSON with custom fields

I'm trying to create a simple REST API with Spring MVC, that returns data in JSON format.
I'm working on a method that returns a list of authors, that's accessed from example.com/api/authors?find=somename
I have a JPA entity called Authors. I have a #Service that fetches a List<Author> collection. The Author entity has properties, like id, firstName, lastName, birthDate.
What I'm trying to achieve is that my JSON result is something like:
{
"data": [
{
"id": 1,
"name": "Leo Tolstoi",
"age": 49
},
{
"id": 2,
"name": "Billy Shakespeare",
"age": 32
}
]
}
As you can see, the result has 2 fields that are not directly from the entity, rather should be generated from Author entity's values. The name field is author.getFirstName() + " " + author.getLastName() and the age is someUtilityClass.calcAge(author.getBirthDate())
I'm trying to figure out how to get this sort of output using GSON.
What I could do, is fetch data from the service class and iterate over it, saving each iteration row to a Map (or something, maybe just save each row to something like List<AuthorJson> entity, which has fields like id, name, age). But this approach doesn't seem to be very clean.
Can you guys suggest any solutions?
You should use a custom Serializer for Author.
Documentation
Since you just need a Serializer, here is an example of what you can do. Note that age will be off by one most of the time.
public static void main(String[] args) {
GsonBuilder gBuild = new GsonBuilder();
gBuild.registerTypeAdapter(Author.class, new AuthorSerializer());
Author author = new Author();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, 1);
cal.set(Calendar.DAY_OF_MONTH, 1);
author.setBirthDate(cal);
author.setFirstName("John");
author.setLastName("Smith");
Gson gson = gBuild.setPrettyPrinting().create();
System.out.println(gson.toJson(author));
}
private static class AuthorSerializer implements JsonSerializer<Author> {
#Override
public JsonElement serialize(Author src, Type typeOfSrc, JsonSerializationContext context) {
Calendar today = Calendar.getInstance();
int age = today.get(Calendar.YEAR) - src.getBirthDate().get(Calendar.YEAR);
String fullName = src.getFirstName() + " " + src.getLastName();
JsonObject obj = new JsonObject();
obj.addProperty("fullName", fullName);
obj.addProperty("age", age);
return obj;
}
}

Mapping between JSON formats in Java

I'm coming to Java from JavaScript/Ruby. Let's say I've got the following JSON object for an animal:
{
name: {
common: "Tiger",
latin: "Panthera tigris"
}
legs: 4
}
I'm dealing with lots of animal APIs, and I want to normalize them all into my own common format, like:
{
common_name: "Tiger",
latin_name: "Panthera tigris",
limbs: {
legs: 4,
arms: 0
}
}
In, say, JavaScript, this would be straightforward:
normalizeAnimal = function(original){
return {
common_name: original.name.common,
latin_name: original.name.latin,
limbs: {
legs: original.legs || 0,
arms: original.arms || 0
}
}
}
But what about in Java? Using the JSONObject class from org.json, I could go down the road of doing something like this:
public JSONObject normalizeAnimal(JSONObject original) throws JSONException{
JSONObject name = original.getJSONObject("name");
JSONObject limbs = new JSONObject();
JSONObject normalized = new JSONObject();
normalized.put("name_name", name.get("common"));
normalized.put("latin_name", name.get("latin"));
try{
limbs.put("legs", original.get("legs");
}catch(e){
limbs.put("legs", 0);
};
try{
limbs.put("arms", original.get("arms");
}catch(e){
limbs.put("arms", 0);
};
normalized.put("limbs", limbs);
return normalized;
}
This gets worse as the JSON objects I'm dealing with get longer and deeper. In addition to all of this, I'm dealing with many providers for animal objects and I'll eventually be looking to have some succinct configuration format for describing the transformations (like, maybe, "common_name": "name.common", "limbs.legs": "legs").
How would I go about making this suck less in Java?
Use a library like Gson or Jackson and map the JSON to a Java Object.
So you're going to have a bean like
public class JsonAnima {
private JsonName name;
private int legs;
}
public class JsonName {
private String commonName;
private String latinName;
}
which can be easily converted with any library with something like (with Jackson)
ObjectMapper mapper = new ObjectMapper();
JsonAnimal animal = mapper.readValue(jsonString, JsonAnimal.class);
then you can create a "converter" to map the JsonAnimal to you Animal class.
This can be a way of doing it. : )
Some links:
Gson: http://code.google.com/p/google-gson/
Jackson: http://wiki.fasterxml.com/JacksonHome
The pure Java solutions all are challenged to deal with unreliable structure of your source data. If you're running in a JVM, I recommend that you consider using Groovy to do the Parse and the Build of your source JSON. The result ends up looking a lot like the Javascript solution you outlined above:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
def originals = [
'{ "name": { "common": "Tiger", "latin": "Panthera tigris" }, "legs": 4 }',
'{ "name": { "common": "Gecko", "latin": "Gek-onero" }, "legs": 4, "arms": 0 }',
'{ "name": { "common": "Liger" }, "legs": 4, "wings": 2 }',
'{ "name": { "common": "Human", "latin": "Homo Sapien" }, "legs": 2, "arms": 2 }'
]
originals.each { orig ->
def slurper = new JsonSlurper()
def parsed = slurper.parseText( orig )
def builder = new JsonBuilder()
// This builder looks a lot like the Javascript solution, no?
builder {
common_name parsed.name.common
latin_name parsed.name.latin
limbs {
legs parsed.legs ?: 0
arms parsed.arms ?: 0
}
}
def normalized = builder.toString()
println "$normalized"
}
Running the script above deals with "jagged" JSON (not all elements have the same attributes) and outputs like...
{"common_name":"Tiger","latin_name":"Panthera tigris","limbs":{"legs":4,"arms":0}}
{"common_name":"Gecko","latin_name":"Gek-onero","limbs":{"legs":4,"arms":0}}
{"common_name":"Liger","latin_name":null,"limbs":{"legs":4,"arms":0}}
{"common_name":"Human","latin_name":"Homo Sapien","limbs":{"legs":2,"arms":2}}
If you'll be using this for many different types of objects, I would suggest to use reflection instead of serializing each object manually. By using reflection you will not need to create methods like normalizeAnimal, you just create one method or one class to do the serialization to json format.
If you search for "mapping json java" you'll find some useful references. Like gson. Here is an example that is on their website:
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"}
///Note that you can not serialize objects with circular references since that will result in infinite recursion.
//(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
//==> obj2 is just like obj
You can try little jmom java library
JsonValue json = JsonParser.parse(stringvariablewithjsoninside);
Jmom mom = Jmom.instance()
.copy("/name/common", "/common_name", true)
.copy("/name/latin", "/latin_name", true)
.copy("/arms", "/limbs/arms", true)
.copy("/legs", "/limbs/legs", true)
.remove("/name")
;
mom.apply(json);
String str = json.toPrettyString(" ");

Categories