I am new to JSON data format and java programming language; hence, I cannot find a valid answer. Actually, I have to read this API https://www.doviz.com/api/v1/currencies/all/latest, and obtain some important contents from this API. Hence, I decided to use google's GSON class, and I wrote this code.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Scanner;
import com.google.gson.Gson;
public class Main {
public static void main( String[] args ) throws Exception{
String line = "";
String jsonString = "";
URL myUrl = new URL("https://www.doviz.com/api/v1/currencies/all/latest");
BufferedReader reader = new BufferedReader( new InputStreamReader(myUrl.openStream()) );
while( (line = reader.readLine()) != null ){
System.out.println(line);
jsonString += line;
}
reader.close();
jsonString = jsonString.substring(1, jsonString.length() - 1);
Gson gson = new Gson();
Currency json = gson.fromJson(jsonString, Currency.class);
}
}
public class Currency {
public double getSelling(){
return selling;
}
public double getBuyiing(){
return buying;
}
public String getCode(){
return code;
}
private double selling;
private transient long update_date;
private transient int currency;
private double buying;
private transient double change_rate;
private transient String name;
private transient String full_name;
private String code;
}
This code causes error, and as far as I guess, the main reason for the errors is that I do not put backslash in son string like this: "{\"brand\":\"Jeep\", \"doors\": 3}"
What I am wondering is why we need to put these backslash ?
There are 2 things to mention.
The " character is the String delimiter. A String starts at a " mark, and ends at the next one. (When initializing it explicitly, not using other variables) If you want to include " character in your String, you need to escape it like \" - so Java knows that it is not the end of the String, just a part of the content.
In JSON you should use single quotes ' - many libraries accept double quotes also, but it is not correct actually, and if any api complains about them, the API is right.
So your payload should look like {'brand': 'Jeep', 'doors': 3} I mean the other way around of course.
When you receive a JSON output from the api, you can directly use the output and can deserialize it. You don't need to have escape characters in the json string. They are required when you define the json string yourself. For example String s = "{\"current_user_url\"}"; because it is the compiler which forces you to escape it. But the json output you are getting as an API response is in a variable and if type of variable and the content you are assigning to it are same then compiler can't compain about that.
Now, I have used your code only but used the Github public API and I am able to deserialize the output json without any operation on the output string whatsoever like escaping the "" or changing "" to ''.
class Github {
private String current_user_url;
private String authorizations_url;
public String getCurrent_user_url() {
return current_user_url;
}
public void setCurrent_user_url(String current_user_url) {
this.current_user_url = current_user_url;
}
public String getAuthorizations_url() {
return authorizations_url;
}
public void setAuthorizations_url(String authorizations_url) {
this.authorizations_url = authorizations_url;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
String line = "";
String jsonString = "";
URL myUrl = new URL("https://api.github.com");
BufferedReader reader = new BufferedReader( new InputStreamReader(myUrl.openStream()) );
while( (line = reader.readLine()) != null ){
//System.out.println(line);
jsonString += line;
}
reader.close();
System.out.println(jsonString);
Gson g = new Gson();
Github gi = g.fromJson(jsonString, Github.class);
System.out.println(gi.getAuthorizations_url());
System.out.println(gi.getCurrent_user_url());
}
I also defined the json string myself and desrialized it using GSON. In this case while defining the json string I needed to escape the double quotes as shown below:
String s = "{\"current_user_url\":\"http://test.com/user\"}";
Gson g = new Gson();
Github gi = g.fromJson(s, Github.class);
System.out.println(gi.getCurrent_user_url());
Also, JSON strings should contain double quotes only and if you use single quotes then you may get an error.
Related
I have a trouble finding a way how to parse JSONArray.
It looks like this:
[{"name":"name1","url":"url1"},{"name":"name2","url":"url2"},...]
I know how to parse it if the JSON was written differently (In other words, if I had json object returned instead of an array of objects).
But it's all I have and have to go with it.
*EDIT: It is a valid json. I made an iPhone app using this json, now I need to do it for Android and cannot figure it out.
There are a lot of examples out there, but they are all JSONObject related. I need something for JSONArray.
Can somebody please give me some hint, or a tutorial or an example?
Much appreciated !
use the following snippet to parse the JsonArray.
JSONArray jsonarray = new JSONArray(jsonStr);
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
String name = jsonobject.getString("name");
String url = jsonobject.getString("url");
}
I'll just give a little Jackson example:
First create a data holder which has the fields from JSON string
// imports
// ...
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyDataHolder {
#JsonProperty("name")
public String mName;
#JsonProperty("url")
public String mUrl;
}
And parse list of MyDataHolders
String jsonString = // your json
ObjectMapper mapper = new ObjectMapper();
List<MyDataHolder> list = mapper.readValue(jsonString,
new TypeReference<ArrayList<MyDataHolder>>() {});
Using list items
String firstName = list.get(0).mName;
String secondName = list.get(1).mName;
public static void main(String[] args) throws JSONException {
String str = "[{\"name\":\"name1\",\"url\":\"url1\"},{\"name\":\"name2\",\"url\":\"url2\"}]";
JSONArray jsonarray = new JSONArray(str);
for(int i=0; i<jsonarray.length(); i++){
JSONObject obj = jsonarray.getJSONObject(i);
String name = obj.getString("name");
String url = obj.getString("url");
System.out.println(name);
System.out.println(url);
}
}
Output:
name1
url1
name2
url2
Create a class to hold the objects.
public class Person{
private String name;
private String url;
//Get & Set methods for each field
}
Then deserialize as follows:
Gson gson = new Gson();
Person[] person = gson.fromJson(input, Person[].class); //input is your String
Reference Article: http://blog.patrickbaumann.com/2011/11/gson-array-deserialization/
In this example there are several objects inside one json array. That is,
This is the json array: [{"name":"name1","url":"url1"},{"name":"name2","url":"url2"},...]
This is one object: {"name":"name1","url":"url1"}
Assuming that you have got the result to a String variable called jSonResultString:
JSONArray arr = new JSONArray(jSonResultString);
//loop through each object
for (int i=0; i<arr.length(); i++){
JSONObject jsonProductObject = arr.getJSONObject(i);
String name = jsonProductObject.getString("name");
String url = jsonProductObject.getString("url");
}
public class CustomerInfo
{
#SerializedName("customerid")
public String customerid;
#SerializedName("picture")
public String picture;
#SerializedName("location")
public String location;
public CustomerInfo()
{}
}
And when you get the result; parse like this
List<CustomerInfo> customers = null;
customers = (List<CustomerInfo>)gson.fromJson(result, new TypeToken<List<CustomerInfo>>() {}.getType());
A few great suggestions are already mentioned.
Using GSON is really handy indeed, and to make life even easier you can try this website
It's called jsonschema2pojo and does exactly that:
You give it your json and it generates a java object that can paste in your project.
You can select GSON to annotate your variables, so extracting the object from your json gets even easier!
My case
Load From Server Example..
int jsonLength = Integer.parseInt(jsonObject.getString("number_of_messages"));
if (jsonLength != 1) {
for (int i = 0; i < jsonLength; i++) {
JSONArray jsonArray = new JSONArray(jsonObject.getString("messages"));
JSONObject resJson = (JSONObject) jsonArray.get(i);
//addItem(resJson.getString("message"), resJson.getString("name"), resJson.getString("created_at"));
}
Create a POJO Java Class for the objects in the list like so:
class NameUrlClass{
private String name;
private String url;
//Constructor
public NameUrlClass(String name,String url){
this.name = name;
this.url = url;
}
}
Now simply create a List of NameUrlClass and initialize it to an ArrayList like so:
List<NameUrlClass> obj = new ArrayList<NameUrlClass>;
You can use store the JSON array in this object
obj = JSONArray;//[{"name":"name1","url":"url1"}{"name":"name2","url":"url2"},...]
Old post I know, but unless I've misunderstood the question, this should do the trick:
s = '[{"name":"name1","url":"url1"},{"name":"name2","url":"url2"}]';
eval("array=" + s);
for (var i = 0; i < array.length; i++) {
for (var index in array[i]) {
alert(array[i][index]);
}
}
URL url = new URL("your URL");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
//setting the json string
String finalJson = buffer.toString();
//this is your string get the pattern from buffer.
JSONArray jsonarray = new JSONArray(finalJson);
I am struggling with some JSON parsing (with Google's GSON library).
Here is my minimal code example:
Gson gson = new Gson();
String line = "{\"method\":\"GET\",\"status\":\"200 - OK\"}";
AnalysisReport report = gson.fromJson(line, AnalysisReport.class); //this works
JsonReader reader = new JsonReader(new StringReader(line));
reader.setLenient(true); //accept malformed input
while (reader.hasNext()) {
report = gson.fromJson(reader, AnalysisReport.class); //this doesn't work
}
reader.close();
I get the following exception: (the string is 36 chars long)
Expected BEGIN_OBJECT but was END_DOCUMENT at line 1 column 37
My ReportAnalysis class looks like this:
public class AnalysisReport {
#SerializedName("method")
private String method;
#SerializedName("status")
private String status;
AnalysisReport(){
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getStatus() {
return status;
}
}
I do not see why my code is not working. I followed the exmaple from Google
= = = EDIT = = =
The reader.hasNext() method always returns true. It seams that the method does not consume any tokens from the stream. But somehow still moves to the end of the stream and failes reading objects.
The problem was indeed the loop (facepalm). This works perfectly fine:
JsonReader reader = new JsonReader(new StringReader(line));
reader.setLenient(true); //accept malformed input
report = gson.fromJson(reader, AnalysisReport.class);
Thanks
I just removed loop and its working fine .
String line = "{\"method\":\"GET\",\"status\":\"200 - OK\"}";
AnalysisReport report = new AnalysisReport();
Gson gson = new GsonBuilder().create();
JsonReader reader = new JsonReader(new StringReader(line));
reader.setLenient(true); //accept malformed input
report = gson.fromJson(line, AnalysisReport.class); //this doesn't work
reader.close();
System.out.println(report.toString());
I would like to pass some values i have from a string in to double variables. the string output looks like this:
{
"high":"1635.07",
"last":"1635.07",
"timestamp":"1489299397",
"volume":"321.34139374",
"vwap":"1602.72987907",
"low":"1595.03",
"ask":"1635.89",
"bid":"1605.10"
}
I just want this data to be like:
double high = (value of high in string);
double last = (value of last in string);
ect...
Im having trouble as java throws an error I believe because of the mix of words and numbers.
Thanks in advance for the help.
code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JOptionPane;
public class btc {
private final String USER_AGENT = "Mozilla/5.0";
public static void main(String[] args) throws Exception {
btc http = new btc();
http.sendGet();
}
// HTTP GET request
private void sendGet() throws Exception {
String url = "https://api.quadrigacx.com/v2/ticker?book=btc_cad";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
System.out.println("\nSending 'GET' request to URL : " + url);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
//write to variables
String test = response.toString();
//double high = test("high");
//Double high = Double.parseDouble(test);
System.out.println(test);
//print result
//JOptionPane.showMessageDialog(null, response.toString());
}
}
As already mentioned in the comments what you receiving from the server is a JSON object as documented in QuadrigaCX's API description so it should be parsed as such as the order of the members may vary aswell as the whitespace.
What's interesting about this JSON string is that all values are actually strings as they are enclosed in double quotation marks. But these strings contain values that can be interpreted and parsed as double.
Using minimal-json, which is a minimalistic Java library that allows you to parse JSON and access contained values directly. The following code makes use of it and "reads" high and last as double values:
JsonObject jsonObject = Json.parse(responseBody).asObject();
double high = Double.parseDouble(jsonObject.get("high").asString());
double last = Double.parseDouble(jsonObject.get("last").asString());
Here responseBody corresponds to what you have named test in your sendGet method and is the response from the web server as one string.
I'm trying to parse the following url:
http://api.crossref.org/works?rows=2
When I parse it through Gson, I got some records but somehow some others stay null.
Here is my code:
BufferedReader in = new BufferedReader(new InputStreamReader(url_tdm.openStream(), "UTF-8"));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = in.read(chars)) != -1)
buffer.append(chars, 0, read);
String jsonLine = buffer.toString();
JsonReader reader = new JsonReader(new StringReader(jsonLine));
reader.setLenient(true); // this is for Malformed json
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
Crossref answer = gson.fromJson(reader, Crossref.class );
List<Items> ao = answer.message.items;
public class Crossref {
public Message message;}
public class Message {
public List<Items> items;}
public class Items {
public List<String> containerTitle;
public List<String> ISSN;
public String publisher;
public List<String> title;
public String DOI;
public String type;}
So as a result of my code above, I can get container-title, publisher and title values. But ISSN and DOIs are null.
I used a FieldNamingPolicy because "container-title" contains a dash and I could not name my field like that in java (so I wrote it as camel case containerTitle).
I am not sure if this affects DOI and ISSN records which are upper case or is it something totally different?
The best way to fix something like this is to use a gson custom deserializer
I suggest that you read this other question to see a good exemple: How do I write a custom JSON deserializer for Gson?
And you can find some other greats exemples and explanations here
I'm learning Java, so I decided to toy around with the GW2 with the hope of coding something useful: API:http://wiki.guildwars2.com/wiki/API:Main
I'm trying to get the following data: https://api.guildwars2.com/v1/world_names.json
into a Java String, this is my code:
public static void main(String[] args) {
URL url = null;
String jsonData = "";
try {
url = new URL("https://api.guildwars2.com/v1/world_names.json");
InputStream is = url.openStream();
Scanner scan = new Scanner(is);
while(scan.hasNext()) {
jsonData += scan.next();
}
scan.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(jsonData);
}
The problem is I'm losing the format of the Strings (I'm missing the blank characters that separate words).
This is what you see if you access the URL:
[{"id":"1009","name":"Fort Aspenwood"},
{"id":"1005","name":"Maguuma"}, {"id":"1008","name":"Jade Quarry"},
This is what I get in my String:
{"id":"1009","name":"FortAspenwood"}, {"id":"1005","name":"Maguuma"},
{"id":"1008","name":"JadeQuarry"}
How can I fix that? am I doing something wrong?
My final goal is to convert this data to an object, and then be able to ask for an specific ID or NAME to the api and get more data, such as maps or events, but first things first, since I'm learning and I can't get the String right..
Thank you for reading,
Right from the documentation:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
You don't want any sort of tokenization, so you can borrow a one-liner from Stupid Scanner tricks:
final String jsonData = new Scanner(is).useDelimiter("\\A").next();
which consumes the entire input stream in one line.
N.B. if you do stick with using a loop, you should use a StringBuilder instead of concatenation (jsonData += scan.next();) because that operation has quadratic asymptotic runtime.
However, I strongly recommend that you use Jackson for all your real-world JSON processing uses.
One way to approach this problem is to use a library, like Jackson, that knows how to parse json input. Here is an example program that goes out to the url you provided and creates a List of DataTransferObject.
This code depends on http://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl/1.9.13
This is not strictly speaking the answer to your question but is another approach.
package stackoverflow;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.net.URL;
import java.util.List;
public class JsonParser {
private static final String urlString = "https://api.guildwars2.com/v1/world_names.json";
public static void main(String[] args) throws IOException {
JsonParser parser = new JsonParser();
URL url = new URL(urlString);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(url.openStream());
List<DataTransferObject> dtoList = mapper.readValue(root, new TypeReference<List<DataTransferObject>>(){});
for(DataTransferObject dto : dtoList) {
System.out.println("DTO: " + dto);
}
}
public static class DataTransferObject {
public int id;
public String name;
#Override
public String toString() {
return "ID: " + id + " NAME: " + name;
}
}
}
As I can see you are doing:
while(scan.hasNext()) {
jsonData += scan.next();
}
next() returns the next token which is separated by spaces, new lines etc. Now since you have to get the whole line from your JSON data, you can do:
while(scan.hasNextLine()) {
jsonData += scan.nextLine();
}