Related
I'm new here and I'm currently working on a standalone source code parser with eclipse-jdt. I have currently an issue that I can't get any further with. The source code parser should write (in this case) a compiler message in a log file:
The following code is from a visitor:
for (IProblem problem : problems) {
if (problem.isError()) {
final String msg = "Problem count: " + problems.length + " in " + resource.getAbsolutePath()
+ "\n\tERROR: " + problem.getSourceLineNumber() + " > " + problem.getMessage();
logger.log(Level.INFO, msg);
continue; // do not count errors
}
// ...
logCompilerMessage(getFullQualifiedName(), mainAuthor, problem);
}
For an example, while parsing the method readData:
package testproj.pckg.billing;
//...
public class Bill {
private boolean readData(MODETYPE modeType) {
// MODETYPE is an enum in other class but in the same package
}
}
The program will "classified" the enum MODETYPE as a error which is in class Bill2.java:
package testproj.pckg.billing;
// ...
public class Bill2 {
// ...
}
enum MODETYPE {
// ...
}
The output will be looking like this:
Problem count: 8 in E:\ws\preview\project\src\testproj\pckg\billing\Bill.java
ERROR: 1925 > MODETYPE cannot be resolved to a type
And this is my parse method:
private void parse(ProjectInfo project, File resource) {
final ASTParser parser = ASTParser.newParser(AST.JLS11);
parser.setResolveBindings(true);
parser.setBindingsRecovery(true);
parser.setStatementsRecovery(true);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setCompilerOptions(project.getCompilerOptions());
final Path sourcePath = Paths.get(resource.toURI());
final char[] source = sourceToChar(sourcePath);
if (source == null) {
return;
}
parser.setSource(source);
parser.setUnitName(resource.getName());
final String[] sources = project.getProjectRelatedSources();
final String[] classpaths = project.getProjectRelatedClasspaths();
final String[] encoders = listOfEncoders(sources);
parser.setEnvironment(classpaths, sources, encoders, true);
// accept visitor(s)
}
EDIT: I forgot to show you my getCompilerOptions method:
private Map<String, String> getCompilerOptions(ProjectInfo project) {
final Map<String, String> list = JavaCore.getOptions();
list.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_11);
list.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_11);
list.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.ENABLED);
list.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
final Config config = new Config(project.getProjectPath() + File.separator + ".settings",
"org.eclipse.jdt.core.prefs");
for (String key : config.keySet()) {
list.put(key, config.value(key));
}
return list;
}
Config is just a handler for property file which I used to initialize the program. In this case, I read the property file org.eclipse.jdt.core.prefs from the eclipse project and return it as a Map.
Everything is working and correctly detected on our IDE but somehow not on the standalone parser.
Can someone help me with it? Thank you in advice!
Best regards,
lftdbmr
This might be a dumb question but what is the simplest way to read and parse JSON from URL in Java?
In Groovy, it's a matter of few lines of code. Java examples that I find are ridiculously long (and have huge exception handling block).
All I want to do is to read the content of this link.
Using the Maven artifact org.json:json I got the following code, which I think is quite short. Not as short as possible, but still usable.
package so4308554;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import org.json.JSONException;
import org.json.JSONObject;
public class JsonReader {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void main(String[] args) throws IOException, JSONException {
JSONObject json = readJsonFromUrl("https://graph.facebook.com/19292868552");
System.out.println(json.toString());
System.out.println(json.get("id"));
}
}
Here are couple of alternatives versions with Jackson (since there are more than one ways you might want data as):
ObjectMapper mapper = new ObjectMapper(); // just need one
// Got a Java class that data maps to nicely? If so:
FacebookGraph graph = mapper.readValue(url, FaceBookGraph.class);
// Or: if no class (and don't need one), just map to Map.class:
Map<String,Object> map = mapper.readValue(url, Map.class);
And specifically the usual (IMO) case where you want to deal with Java objects, can be made one liner:
FacebookGraph graph = new ObjectMapper().readValue(url, FaceBookGraph.class);
Other libs like Gson also support one-line methods; why many examples show much longer sections is odd. And even worse is that many examples use obsolete org.json library; it may have been the first thing around, but there are half a dozen better alternatives so there is very little reason to use it.
The easiest way:
Use gson, google's own goto json library. https://code.google.com/p/google-gson/
Here is a sample. I'm going to this free geolocator website and parsing the json and displaying my zipcode. (just put this stuff in a main method to test it out)
String sURL = "http://freegeoip.net/json/"; //just a string
// Connect to the URL using java's native library
URL url = new URL(sURL);
URLConnection request = url.openConnection();
request.connect();
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
String zipcode = rootobj.get("zip_code").getAsString(); //just grab the zipcode
If you don't mind using a couple libraries it can be done in a single line.
Include Apache Commons IOUtils & json.org libraries.
JSONObject json = new JSONObject(IOUtils.toString(new URL("https://graph.facebook.com/me"), Charset.forName("UTF-8")));
Maven dependency:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
I have done the json parser in simplest way, here it is
package com.inzane.shoapp.activity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
System.out.println(line);
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
System.out.println("error on parse data in jsonparser.java");
}
// return JSON String
return jObj;
}
}
this class returns the json object from the url
and when you want the json object you just call this class and the method in your Activity class
my code is here
String url = "your url";
JSONParser jsonParser = new JSONParser();
JSONObject object = jsonParser.getJSONFromUrl(url);
String content=object.getString("json key");
here the "json key" is denoted that the key in your json file
this is a simple json file example
{
"json":"hi"
}
Here "json" is key and "hi" is value
This will get your json value to string content.
Use HttpClient to grab the contents of the URL. And then use the library from json.org to parse the JSON. I've used these two libraries on many projects and they have been robust and simple to use.
Other than that you can try using a Facebook API java library. I don't have any experience in this area, but there is a question on stack overflow related to using a Facebook API in java. You may want to look at RestFB as a good choice for a library to use.
I have found this to be the easiest way by far.
Use this method:
public static String getJSON(String url) {
HttpsURLConnection con = null;
try {
URL u = new URL(url);
con = (HttpsURLConnection) u.openConnection();
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
return sb.toString();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (con != null) {
try {
con.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return null;
}
And use it like this:
String json = getJSON(url);
JSONObject obj;
try {
obj = new JSONObject(json);
JSONArray results_arr = obj.getJSONArray("results");
final int n = results_arr.length();
for (int i = 0; i < n; ++i) {
// get the place id of each object in JSON (Google Search API)
String place_id = results_arr.getJSONObject(i).getString("place_id");
}
}
It's very easy, using jersey-client, just include this maven dependency:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.25.1</version>
</dependency>
Then invoke it using this example:
String json = ClientBuilder.newClient().target("http://api.coindesk.com/v1/bpi/currentprice.json").request().accept(MediaType.APPLICATION_JSON).get(String.class);
Then use Google's Gson to parse the JSON:
Gson gson = new Gson();
Type gm = new TypeToken<CoinDeskMessage>() {}.getType();
CoinDeskMessage cdm = gson.fromJson(json, gm);
I wanted to add an updated answer here since (somewhat) recent updates to the JDK have made it a bit easier to read the contents of an HTTP URL.
Like others have said, you'll still need to use a JSON library to do the parsing, since the JDK doesn't currently contain one.
Here are a few of the most commonly used JSON libraries for Java:
org.JSON
FasterXML Jackson
GSON
To retrieve JSON from a URL, this seems to be the simplest way using strictly JDK classes (but probably not something you'd want to do for large payloads), Java 9 introduced: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#readAllBytes()
try(java.io.InputStream is = new java.net.URL("https://graph.facebook.com/me").openStream()) {
String contents = new String(is.readAllBytes());
}
To parse the JSON using the GSON library, for example
com.google.gson.JsonElement element = com.google.gson.JsonParser.parseString(contents); //from 'com.google.code.gson:gson:2.8.6'
The Oracle Documentation describes how
an HttpRequest is built and then
sent by the HttpClient to the URL
in just a few lines of code, by using only the Java Class Library. Put this code into your main method:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com/"))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
The response consists of a JSON object { ... } and can be further processed in your application.
Here I printed it to the console, just to confirm it works:
System.out.println(request);
This is available for Java Versions 11+
I am not sure if this is efficient, but this is one of the possible ways:
Read json from url use url.openStream() and read contents into a string.
construct a JSON object with this string (more at json.org)
JSONObject(java.lang.String source)
Construct a JSONObject from a source JSON text string.
Here's a full sample of how to parse Json content. The example takes the Android versions statistics (found from Android Studio source code here, which links to here).
Copy the "distributions.json" file you get from there into res/raw, as a fallback.
build.gradle
implementation 'com.google.code.gson:gson:2.8.6'
manifest
<uses-permission android:name="android.permission.INTERNET" />
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState != null)
return
thread {
// https://cs.android.com/android/platform/superproject/+/studio-master-dev:tools/adt/idea/android/src/com/android/tools/idea/stats/DistributionService.java
var root: JsonArray
Log.d("AppLog", "loading...")
try {
HttpURLConnection.setFollowRedirects(true)
val statsUrl = "https://dl.google.com/android/studio/metadata/distributions.json" //just a string
val url = URL(statsUrl)
val request: HttpURLConnection = url.openConnection() as HttpURLConnection
request.connectTimeout = 3000
request.connect()
InputStreamReader(request.content as InputStream).use {
root = JsonParser.parseReader(it).asJsonArray
}
} catch (e: Exception) {
Log.d("AppLog", "error while loading from Internet, so using fallback")
e.printStackTrace()
InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
root = JsonParser.parseReader(it).asJsonArray
}
}
val decimalFormat = DecimalFormat("0.00")
Log.d("AppLog", "result:")
root.forEach {
val androidVersionInfo = it.asJsonObject
val versionNickName = androidVersionInfo.get("name").asString
val versionName = androidVersionInfo.get("version").asString
val versionApiLevel = androidVersionInfo.get("apiLevel").asInt
val marketSharePercentage = androidVersionInfo.get("distributionPercentage").asFloat * 100f
Log.d("AppLog", "\"$versionNickName\" - $versionName - API$versionApiLevel - ${decimalFormat.format(marketSharePercentage)}%")
}
}
}
}
As alternative to the dependency, you can also use this instead:
InputStreamReader(request.content as InputStream).use {
val jsonArray = JSONArray(it.readText())
}
and the fallback:
InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
val jsonArray = JSONArray(it.readText())
}
The result of running this:
loading...
result:
"Ice Cream Sandwich" - 4.0 - API15 - 0.20%
"Jelly Bean" - 4.1 - API16 - 0.60%
"Jelly Bean" - 4.2 - API17 - 0.80%
"Jelly Bean" - 4.3 - API18 - 0.30%
"KitKat" - 4.4 - API19 - 4.00%
"Lollipop" - 5.0 - API21 - 1.80%
"Lollipop" - 5.1 - API22 - 7.40%
"Marshmallow" - 6.0 - API23 - 11.20%
"Nougat" - 7.0 - API24 - 7.50%
"Nougat" - 7.1 - API25 - 5.40%
"Oreo" - 8.0 - API26 - 7.30%
"Oreo" - 8.1 - API27 - 14.00%
"Pie" - 9.0 - API28 - 31.30%
"Android 10" - 10.0 - API29 - 8.20%
I'm using the PubNub API with Java for pulling data from MtGox.
When retrieving data, the API delivers it in form of a JSONObject, which represents a tree structure of JSON data. Trying to extract bits of information directly from a JSONObject produces ugly code with lots of calls to getJSONObject(String), for which again exceptions might need to be handled.
Therefor, I'm looking for a convenient way to extract information from the JSONObject responses. So far, I've come across the possibility to convert the JSONObject into a POJO and then access the POJO. For conversion, I found the ObjectMapper from the Jackson library, which does a nice job here:
public void successCallback(String channel, Object message) {
JSONObject messageJson = (JSONObject) message;
ObjectMapper mapper = new ObjectMapper();
Message myMessage = mapper.readValue(messageJson.toString(), Message.class);
// do stuff with myMessage here
}
This approach has the disadvantage that I have to write my own POJO classes, e.g. the Message class in the above example, because I could not find these classes ready to use anywhere.
How to conveniently access the information stored in the JSONObject?
PubNub Java Class for MtGox JSON API
It's easy to create a ready made Java Class for ingesting the live feed provided by Mt.Gox This is a work-in-progress post to show you how to access the PubNub Data Feed from Mt.Gox as shown in the Dev Console live feed!
Official Bitcoin Wiki JSON Streaming API
We will be working from the Bitcoin wiki feed instructions provided by Bitcoin official Wiki: https://en.bitcoin.it/wiki/MtGox/API/Pubnub - continue reading below the screenshot to continue.
To see the live real-time data feed we will be using, please checkout the following two links:
Live Feed Trade Events (Buy/Sell Feed): https://www.pubnub.com/console?sub=sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe&pub=demo&channel=dbf1dee9-4f2e-4a08-8cb7-748919a71b21&origin=pubsub.pubnub.com&ssl=true
Live Feed Ticker Updates (Price Changes): https://www.pubnub.com/console?sub=sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe&pub=demo&channel=d5f06780-30a8-4a48-a2f8-7ed181b4a13f&origin=pubsub.pubnub.com&ssl=true
Trade Lag Example: https://www.mtgox.com/lag.html
PubNub Java SDK Docs
We will be using the PubNub Java SDK Docs
http://www.pubnub.com/docs/java/javase/overview/data-push.html
Specifically we'll be using the mtgox.subcribe(...) instance method to focus our efforts which looks like the following:
Download JAR or Source: https://github.com/pubnub/mtgox
import org.json.JSONObject;
import com.pubnub.mtgox.MtGox;
import com.pubnub.mtgox.MtGoxCallback;
public class PubnubMtGoxSample {
public static void main(String[] args) {
MtGox mtgx = new MtGox();
mtgx.subscribe("ticker.BTCUSD", new MtGoxCallback(){
#Override
public void callback(JSONObject data) {
try {
String channel_name = data.getString("channel_name");
String avg_value = data.getJSONObject("ticker").getJSONObject("avg").getString("value");
System.out.println(channel_name + " : " + avg_value);
} catch (Exception e) {}
}});
}
}
See Full MtGox Example with Java Source Code - https://github.com/pubnub/mtgox/blob/master/java/examples/PubnubMtGoxSample.java
To compile the example got to https://github.com/pubnub/mtgox/tree/master/java and run
javac -cp Pubnub-MtGox.jar:libs/json-20090211.jar examples/PubnubMtGoxSample.java
And then to RUN:
java -cp .:examples/:Pubnub-MtGox.jar:Pubnub-StandardEdition-3.5.6.jar:libs/json-20090211.jar:libs/bcprov-jdk15on-1.47.jar:libs/slf4j-api-1.7.5.jar:libs/slf4j-nop-1.7.5.jar PubnubMtGoxSample
The Concept
For me, the best solution was to convert the JSONObjects from the PubNub API to bean classes which I found in the MtGox module of the XChange library.
Admitted, this approach adds quite a bit of glue code as you can see at the end of this answer, but I think it's worth the trouble, because after the conversion, the code gets much simpler. E.g. for getting the rate and currency from the ticker at which BTC was last traded, you can simply write
ticker.getLast().getValue()
and
ticker.getLast().getCurrency()
How To Do It
The mtgox module of the XChange library is available as a maven artifact, which is very convenient. You only need to add this module as a dependency to your project and the project setup is done.
In the xchange-mtgox module, you will find the package com.xeiam.xchange.mtgox.v2.dto.marketdata with the two calsses MtGoxTrade and MtGoxTicker.
Converting from JSONObject to one of these classes is easy with the Jackson ObjectMapper. As an advantage, the Jackson library is automatically imported as a transitive dependency of the xchange-mtgox maven artifact. That means that if you're using maven, you don't even have to write a single line of code to add it to your project.
Below is a complete runnable Example. Most is standard code for using PubNub. The important bits are between the marks // BEGIN OF IMPORTANT PART and // END OF IMPORTANT PART.
public class PubNubMtGoxBeanExample {
private static final String MTGOXPUBNUB_SUBSCRIBE_KEY = "sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe";
private static final String MTGOXPUBNUB_BTCEUR_CHANNEL = "0bb6da8b-f6c6-4ecf-8f0d-a544ad948c15";
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public static void main(String[] args) throws PubnubException {
Pubnub pubnub = new Pubnub("demo", MTGOXPUBNUB_SUBSCRIBE_KEY);
pubnub.subscribe(MTGOXPUBNUB_BTCEUR_CHANNEL, new Callback() {
#Override
public void successCallback(String channel, Object message) {
// BEGIN OF IMPORTANT PART
JSONObject messageJson = (JSONObject) message;
JSONObject tickerJson;
try {
tickerJson = messageJson.getJSONObject("ticker");
} catch (JSONException e) {
throw new RuntimeException(e);
}
MtGoxTicker ticker;
try {
// the following line is the most important, because it maps from the JSONObject to the MtGoxTicker class
ticker = OBJECT_MAPPER.readValue(tickerJson.toString(), MtGoxTicker.class);
} catch (JsonParseException e) {
throw new RuntimeException(e);
} catch (JsonMappingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
String currency = ticker.getLast().getCurrency();
BigDecimal value = ticker.getLast().getValue();
System.out.println(currency + " " + value);
// END OF IMPORTANT PART
}
#Override
public void connectCallback(String channel, Object message) {
System.out.println("connectCallback on channel:" + channel + " : " + message.getClass() + " : " + message.toString());
}
#Override
public void disconnectCallback(String channel, Object message) {
System.out.println("disconnectCallback on channel:" + channel + " : " + message.getClass() + " : " + message.toString());
}
#Override
public void reconnectCallback(String channel, Object message) {
System.out.println("reconnectCallback on channel:" + channel + " : " + message.getClass() + " : " + message.toString());
}
#Override
public void errorCallback(String channel, PubnubError error) {
System.out.println("errorCallback on channel " + channel + " : " + error.toString());
}
});
}
}
For clarity, I've removed the imports, which you can add back in with the appropriate hotkeys in most IDEs (it's Ctrl+Shift+O in Eclipse).
Morevoer, note that there is a performance penalty in this code, which can be avoided by following the answer to the question
How to efficiently map a org.json.JSONObject to a POJO?
How do I print the entire stack trace using java.util.Logger? (without annoying Netbeans).
The question should've originally specified staying within Java SE. Omitting that requirment was an error on my part.
-do-compile:
[mkdir] Created dir: /home/thufir/NetBeansProjects/rainmaker/build/empty
[mkdir] Created dir: /home/thufir/NetBeansProjects/rainmaker/build/generated-sources/ap-source-output
[javac] Compiling 13 source files to /home/thufir/NetBeansProjects/rainmaker/build/classes
[javac] /home/thufir/NetBeansProjects/rainmaker/src/model/TelnetEventProcessor.java:44: error: 'void' type not allowed here
[javac] log.severe(npe.printStackTrace(System.out));
[javac] ^
[javac] 1 error
BUILD FAILED
code with the error:
package model;
import java.util.Observable;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TelnetEventProcessor extends Observable {
private static Logger log = Logger.getLogger(TelnetEventProcessor.class.getName());
private String string = null;
public TelnetEventProcessor() {
}
private void stripAnsiColors() {
Pattern regex = Pattern.compile("\\e\\[[0-9;]*m");
Matcher regexMatcher = regex.matcher(string);
string = regexMatcher.replaceAll(""); // *3 ??
}
public void parse(String string) {
this.string = string;
ifs();
}
// [\w]+(?=\.)
private void ifs() {
log.fine("checking..");
if (string.contains("confusing the hell out of")) {
Pattern pattern = Pattern.compile("[\\w]+(?=\\.)"); //(\w+)\.
Matcher matcher = pattern.matcher(string);
String enemy = null;
GameData data = null;
while (matcher.find()) {
enemy = matcher.group();
}
try {
data = new GameData.Builder().enemy(enemy).build();
log.fine("new data object\t\t" + data.getEnemy());
setChanged();
notifyObservers(data);
} catch (NullPointerException npe) {
log.severe(npe.printStackTrace(System.out));
}
} else if (string.contains("Enter 3-letter city code:")) {
log.fine("found enter city code");
} else {
}
}
}
see also:
https://stackoverflow.com/a/7100975/262852
The severe method is only used to log severe messages without associated throwable information. If you need to log throwable information then you should use the log method instead:
try {
data = new GameData.Builder().enemy(enemy).build();
log.fine("new data object\t\t" + data.getEnemy());
setChanged();
notifyObservers(data);
} catch (NullPointerException npe) {
log.log(Level.SEVERE, npe.getMessage(), npe);
}
Why don't you put the exception in the logger?
You can use this method :
logger.log(Level level, String msg, Throwable thrown)
Maybe a duplicated question? Java - Need a logging package that will log the stacktrace
Below the explanation from the given url
Using log4j
this is done with:
logger.error("An error occurred", exception);
The first argument is a message to be displayed, the second is the
exception (throwable) whose stacktrace is logged.
Another option is commons-logging,
where it's the same:
log.error("Message", exception);
With java.util.logging
this can be done via:
logger.log(Level.SEVERE, "Message", exception);
You don't explicitly print the stack trace; Throwables have stack traces attached to them, and you can pass a Throwable to the log methods:
log(Level level, String msg, Throwable thrown)
You could use Apache ExceptionUtils. In your case
try {
data = new GameData.Builder().enemy(enemy).build();
log.fine("new data object\t\t" + data.getEnemy());
setChanged();
notifyObservers(data);
} catch (NullPointerException npe) {
logger.info(**ExceptionUtils.getFullStackTrace(npe)**);
}
You should redirect the System.err to the logger, the process is not too simple but you can use this code:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LogOutputStream extends ByteArrayOutputStream {//java.io.OutputStream {
private String lineSeparator;
private Logger logger;
private Level level;
public LogOutputStream(Logger logger, Level level) {
super();
this.logger = logger;
this.level = level;
this.lineSeparator = System.getProperty("line.separator");
}
#Override
public void flush() throws IOException {
String record;
synchronized (this) {
super.flush();
record = this.toString();
super.reset();
if ((record.length() == 0) || record.equals(this.lineSeparator)) {
// avoid empty records
return;
}
this.logger.logp(this.level, "", "", record);
}
}
}
And The code to set this (that should called the when you first create the logger
Logger logger = Logger.getLogger("Exception");
LogOutputStream los = new LogOutputStream(logger, Level.SEVERE);
System.setErr(new PrintStream(los, true));
This will redirect the System.err stream to the logger.
You can also try to use ExceptionUtils from apache commons
The exception is due to the printstacktrace method being void, meaning it doesn't return anything. You are trying to do:
log.severe(npe.printStackTrace(System.out));
My guess is that the severe method needs a String and not void.
This might be a dumb question but what is the simplest way to read and parse JSON from URL in Java?
In Groovy, it's a matter of few lines of code. Java examples that I find are ridiculously long (and have huge exception handling block).
All I want to do is to read the content of this link.
Using the Maven artifact org.json:json I got the following code, which I think is quite short. Not as short as possible, but still usable.
package so4308554;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import org.json.JSONException;
import org.json.JSONObject;
public class JsonReader {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void main(String[] args) throws IOException, JSONException {
JSONObject json = readJsonFromUrl("https://graph.facebook.com/19292868552");
System.out.println(json.toString());
System.out.println(json.get("id"));
}
}
Here are couple of alternatives versions with Jackson (since there are more than one ways you might want data as):
ObjectMapper mapper = new ObjectMapper(); // just need one
// Got a Java class that data maps to nicely? If so:
FacebookGraph graph = mapper.readValue(url, FaceBookGraph.class);
// Or: if no class (and don't need one), just map to Map.class:
Map<String,Object> map = mapper.readValue(url, Map.class);
And specifically the usual (IMO) case where you want to deal with Java objects, can be made one liner:
FacebookGraph graph = new ObjectMapper().readValue(url, FaceBookGraph.class);
Other libs like Gson also support one-line methods; why many examples show much longer sections is odd. And even worse is that many examples use obsolete org.json library; it may have been the first thing around, but there are half a dozen better alternatives so there is very little reason to use it.
The easiest way:
Use gson, google's own goto json library. https://code.google.com/p/google-gson/
Here is a sample. I'm going to this free geolocator website and parsing the json and displaying my zipcode. (just put this stuff in a main method to test it out)
String sURL = "http://freegeoip.net/json/"; //just a string
// Connect to the URL using java's native library
URL url = new URL(sURL);
URLConnection request = url.openConnection();
request.connect();
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
String zipcode = rootobj.get("zip_code").getAsString(); //just grab the zipcode
If you don't mind using a couple libraries it can be done in a single line.
Include Apache Commons IOUtils & json.org libraries.
JSONObject json = new JSONObject(IOUtils.toString(new URL("https://graph.facebook.com/me"), Charset.forName("UTF-8")));
Maven dependency:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
I have done the json parser in simplest way, here it is
package com.inzane.shoapp.activity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
System.out.println(line);
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
System.out.println("error on parse data in jsonparser.java");
}
// return JSON String
return jObj;
}
}
this class returns the json object from the url
and when you want the json object you just call this class and the method in your Activity class
my code is here
String url = "your url";
JSONParser jsonParser = new JSONParser();
JSONObject object = jsonParser.getJSONFromUrl(url);
String content=object.getString("json key");
here the "json key" is denoted that the key in your json file
this is a simple json file example
{
"json":"hi"
}
Here "json" is key and "hi" is value
This will get your json value to string content.
Use HttpClient to grab the contents of the URL. And then use the library from json.org to parse the JSON. I've used these two libraries on many projects and they have been robust and simple to use.
Other than that you can try using a Facebook API java library. I don't have any experience in this area, but there is a question on stack overflow related to using a Facebook API in java. You may want to look at RestFB as a good choice for a library to use.
I have found this to be the easiest way by far.
Use this method:
public static String getJSON(String url) {
HttpsURLConnection con = null;
try {
URL u = new URL(url);
con = (HttpsURLConnection) u.openConnection();
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
return sb.toString();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (con != null) {
try {
con.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return null;
}
And use it like this:
String json = getJSON(url);
JSONObject obj;
try {
obj = new JSONObject(json);
JSONArray results_arr = obj.getJSONArray("results");
final int n = results_arr.length();
for (int i = 0; i < n; ++i) {
// get the place id of each object in JSON (Google Search API)
String place_id = results_arr.getJSONObject(i).getString("place_id");
}
}
It's very easy, using jersey-client, just include this maven dependency:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.25.1</version>
</dependency>
Then invoke it using this example:
String json = ClientBuilder.newClient().target("http://api.coindesk.com/v1/bpi/currentprice.json").request().accept(MediaType.APPLICATION_JSON).get(String.class);
Then use Google's Gson to parse the JSON:
Gson gson = new Gson();
Type gm = new TypeToken<CoinDeskMessage>() {}.getType();
CoinDeskMessage cdm = gson.fromJson(json, gm);
I wanted to add an updated answer here since (somewhat) recent updates to the JDK have made it a bit easier to read the contents of an HTTP URL.
Like others have said, you'll still need to use a JSON library to do the parsing, since the JDK doesn't currently contain one.
Here are a few of the most commonly used JSON libraries for Java:
org.JSON
FasterXML Jackson
GSON
To retrieve JSON from a URL, this seems to be the simplest way using strictly JDK classes (but probably not something you'd want to do for large payloads), Java 9 introduced: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#readAllBytes()
try(java.io.InputStream is = new java.net.URL("https://graph.facebook.com/me").openStream()) {
String contents = new String(is.readAllBytes());
}
To parse the JSON using the GSON library, for example
com.google.gson.JsonElement element = com.google.gson.JsonParser.parseString(contents); //from 'com.google.code.gson:gson:2.8.6'
The Oracle Documentation describes how
an HttpRequest is built and then
sent by the HttpClient to the URL
in just a few lines of code, by using only the Java Class Library. Put this code into your main method:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com/"))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
The response consists of a JSON object { ... } and can be further processed in your application.
Here I printed it to the console, just to confirm it works:
System.out.println(request);
This is available for Java Versions 11+
I am not sure if this is efficient, but this is one of the possible ways:
Read json from url use url.openStream() and read contents into a string.
construct a JSON object with this string (more at json.org)
JSONObject(java.lang.String source)
Construct a JSONObject from a source JSON text string.
Here's a full sample of how to parse Json content. The example takes the Android versions statistics (found from Android Studio source code here, which links to here).
Copy the "distributions.json" file you get from there into res/raw, as a fallback.
build.gradle
implementation 'com.google.code.gson:gson:2.8.6'
manifest
<uses-permission android:name="android.permission.INTERNET" />
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState != null)
return
thread {
// https://cs.android.com/android/platform/superproject/+/studio-master-dev:tools/adt/idea/android/src/com/android/tools/idea/stats/DistributionService.java
var root: JsonArray
Log.d("AppLog", "loading...")
try {
HttpURLConnection.setFollowRedirects(true)
val statsUrl = "https://dl.google.com/android/studio/metadata/distributions.json" //just a string
val url = URL(statsUrl)
val request: HttpURLConnection = url.openConnection() as HttpURLConnection
request.connectTimeout = 3000
request.connect()
InputStreamReader(request.content as InputStream).use {
root = JsonParser.parseReader(it).asJsonArray
}
} catch (e: Exception) {
Log.d("AppLog", "error while loading from Internet, so using fallback")
e.printStackTrace()
InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
root = JsonParser.parseReader(it).asJsonArray
}
}
val decimalFormat = DecimalFormat("0.00")
Log.d("AppLog", "result:")
root.forEach {
val androidVersionInfo = it.asJsonObject
val versionNickName = androidVersionInfo.get("name").asString
val versionName = androidVersionInfo.get("version").asString
val versionApiLevel = androidVersionInfo.get("apiLevel").asInt
val marketSharePercentage = androidVersionInfo.get("distributionPercentage").asFloat * 100f
Log.d("AppLog", "\"$versionNickName\" - $versionName - API$versionApiLevel - ${decimalFormat.format(marketSharePercentage)}%")
}
}
}
}
As alternative to the dependency, you can also use this instead:
InputStreamReader(request.content as InputStream).use {
val jsonArray = JSONArray(it.readText())
}
and the fallback:
InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
val jsonArray = JSONArray(it.readText())
}
The result of running this:
loading...
result:
"Ice Cream Sandwich" - 4.0 - API15 - 0.20%
"Jelly Bean" - 4.1 - API16 - 0.60%
"Jelly Bean" - 4.2 - API17 - 0.80%
"Jelly Bean" - 4.3 - API18 - 0.30%
"KitKat" - 4.4 - API19 - 4.00%
"Lollipop" - 5.0 - API21 - 1.80%
"Lollipop" - 5.1 - API22 - 7.40%
"Marshmallow" - 6.0 - API23 - 11.20%
"Nougat" - 7.0 - API24 - 7.50%
"Nougat" - 7.1 - API25 - 5.40%
"Oreo" - 8.0 - API26 - 7.30%
"Oreo" - 8.1 - API27 - 14.00%
"Pie" - 9.0 - API28 - 31.30%
"Android 10" - 10.0 - API29 - 8.20%