I'm using the following code to parse info from a site and it works expect that the older in the last for loop goes out of whack. names() comes out as
["569","570","565","566","567","568","562","563","564"]
those number should be in numeric order but they aren't. Is there a good way to fix this?
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.annotation.SuppressLint;
import android.util.Log;
public class JSON {
private String html;
private String version = "version";
private String pageString = null;
private String urlString = "http://frc-manual.usfirst.org/a/GetAllItems/ManualID=3";
public volatile boolean parsingComplete = true;
public JSON(String page){
this.pageString = page;
}
public String getHTML(){
return html;
}
public String getVersion(){
return version;
}
#SuppressLint("NewApi")
public void readAndParseJSON(String in) {
try {
JSONObject reader = new JSONObject(in);
JSONObject head = reader.getJSONObject("data").getJSONObject("SubChapter").getJSONObject("3").getJSONObject("children").getJSONObject(pageString);
html = head.getString("item_content_text");
if(head.has("children")){
JSONObject children = head.getJSONObject("children");
JSONArray sub1 = new JSONArray(children.names().toString());
for(int i=sub1.length()-1;i>=0;i--){
JSONObject children2 = children.getJSONObject(Integer.toString(sub1.getInt(i)));
html = html + "<h2>" + children2.getString("secdisp")+ " " + children2.getString("item_name") + "</h2>";
html = html + children2.getString("item_content_text");
if(children2.has("children")){
JSONObject children3 = children2.getJSONObject("children");
JSONArray sub2 = new JSONArray(children3.names().toString());
html = html + sub2;
for(int j=sub2.length()-1;j>=0;j--){
JSONObject children4 = children3.getJSONObject((String) sub2.get(j));
html = html + "<h3>" + children4.getString("secdisp")+ " " + children4.getString("item_name") + "</h3>";
html = html + children4.getString("item_content_text");
}
}
}
}
JSONObject main = reader.getJSONObject("data");
version = main.getString("LatestManualUpdate");
parsingComplete = false;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void fetchJSON(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();
String data = convertStreamToString(stream);
readAndParseJSON(data);
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}
The order of the keys in a JSONObject is undefined (see the documentation for keys()). In practice, this means they will likely be ordered according to their hash codes, which is clearly not what you want. If you need to keep these items in a specific order, you could either:
Use a different JSON parser. There are plenty available with a google search; I'd suggest that perhaps a "push-parser" may be the most appropriate type, as this will be guaranteed to give you the items in the object one after another in the order they are defined. json-simple is one such parser. Look at their examples 5 & 6 in the "decoding examples" page. Alternatively, see example 4 for how to change the type of Map it uses for storing JSON objects in its object-model mode, and note that a LinkedHashMap preserves the order the values are added to it.
Sort the list of names before you use them
Change the JSON to use an array of objects which contain the number rather than an object with the numbers as keys, as arrays are (obviously) kept in the order they appear in the original JSON.
You are expecting something that is outside the representational model for JSON.
According to the JSON specification:
"An object is an unordered set of name/value pairs."
The fact that you can imply an order is not relevant. The JSON information model does not recognize that such an ordering exists. That is why most JSON parsers ignore your implied ordering, and many in-memory JSON object representations have no way of recording it.
So what should you do?
My recommendation would be to change your JSON schema. For example, instead of this:
{ "name1" : "value1", "name2" : "value2", "name3" : "value3" }
write:
[ [ "name1", "value1" ], [ "name2", "value2" ], [ "name3", "value3" ] ]
or
[ { "name": "name1", "val" : "value1" },
{ "name": "name2", "val" : "value2" },
{ "name": "name3", "val" : "value3" } ]
... both of which are guaranteed to preserve the order of the entries.
It is also possible to "hack" a solution; i.e. there are ways to get some JSON parsers to preserve the order of name/value pairs that is implied by the serial form. (I'm not going to explain how, because I think it is a really bad idea.)
The problem with doing this is that it ignores interoperability. One of the most important reasons for using JSON (or XML, or any other standard format) is that people can use any spec-conformant software to generate and parse the "stuff" used for data interchange. But what you are doing is taking away that advantage by adding extra requirements that directly contradict the JSON spec.
Related
I'm trying to read a JSON file in my java application using the org/json/json/20171018 repository (http://central.maven.org/maven2/org/json/json/20171018/ -> json-20171018.jar). My JSON file looks like this:
{
"manifest_version": 2,
"name": "Chrome Extension",
"version": "0.1",
"permissions": [
"tabs"
],
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"background": {
"matches": [
"google.de",
"youtube.com",
"wikipedia.de"
],
"scripts": ["background.js"],
"persistent": true
}
}
I'm interested in the background section more specific in the links the background matches to. So I've created first a JSONObject of the whole file, then a JSONObject of the background section and then a JSONArray of the type matches. But unfortunately I'm getting this error showing up when I run the program:
Exception in thread "main" org.json.JSONException: JSONObject["matches"] not found.
at org.json.JSONObject.get(JSONObject.java:520)
at org.json.JSONObject.getJSONArray(JSONObject.java:714)
at Json.main(Json.java:19)
My java code looks like this:
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Json {
public static void main(String[] args){
String loc = new String("chromeAdon/manifest.json");
File file = new File(loc);
try {
String content = new String(Files.readAllBytes(Paths.get(file.toURI())));
JSONObject json = new JSONObject(content);
JSONObject json2 = new JSONObject(json.getJSONObject("background"));
JSONArray jarray = json2.getJSONArray("matches");
for (int i=0;i<jarray.length();i++){
System.out.println(jarray.getString(0));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Does anyone know where my mistake is?
You are wrapping the JSON object returned by getJSONObject("background"), which is not needed.
Try just using the returned object:
JSONObject jsonContent = new JSONObject(content);
JSONObject jsonBackground = jsonContent.getJSONObject("background");
JSONArray jsonArrayMatches = jsonBackground.getJSONArray("matches");
I'm creating a Spring application on backend and my main goal is to manage properties (add/update/delete) in *.properties file. I want to convert this file to JSON and then manipulate it from UI application.
Is there any possibility to convert structure like this:
a.x=1
a.y=2
b.z=3
To JSON like this:
{
"a": {
"x": 1,
"y": 2
},
"b": {
"z": 3
}
}
I found solution to use GSON library, but it creates for me flat structure, not hierarchical, code I used:
Properties props = new Properties();
try (FileInputStream in = new FileInputStream(classPathResource.getFile())) {
props.load(in);
}
String json = new GsonBuilder().enableComplexMapKeySerialization().create().toJson(props);
Is here someone who was facing same problem and maybe found a working project for this? Maybe GSON library can do that?
This solution does involve loads of work, but you will get what you want to achieve using the below code, basically, the idea is to split the key based on the single dot and then create a JsonObject if the same first key is found.
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import org.json.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class SOTest {
public static void main(String[] args) throws IOException {
JSONObject jsonObject = new JSONObject();
FileReader fileReader = new FileReader(new File("C:\\Usrc\\main\\java\\Sample.properties"));
Properties properties = new Properties();
properties.load(fileReader);
Iterator<Entry<Object, Object>> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
Entry<Object, Object> entry = iterator.next();
String value = (String) entry.getKey();
String[] values = value.split("\\.");
JSONObject opt = jsonObject.optJSONObject(values[0]);
if(opt!=null) {
opt.put(values[1],entry.getValue());
}else {
JSONObject object = new JSONObject();
object.put(values[1], entry.getValue());
jsonObject.put(values[0], object);
}
}
System.out.println(jsonObject.toString());
}
}
Output
{"a":{"x":"1","y":"3"},"b":{"z":"10"}}
I have this code and I tried to getting items from this JSON string but it failed.
I'm parsing the Json string from remote host.
package selectDB;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.sql.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.json.simple.*;
public class selectDB
{
public static void main(String[] args) throws IOException, ParseException
{
String s = "";
URL u = new URL("http://192.168.3.1/android/select.php");
URLConnection c = u.openConnection();
InputStream r = c.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(r));
for(String line; (line = reader.readLine()) != null;)
{
s+=line;
}
System.out.println(s);
}
}
the result is
{"result" : "true" , "messages" : [{"id":"866343023633578","latitute":"27","longitude":"31","number_phone":"01113171374"},{"id":"352168066354050","latitute":"27","longitude":"31","number_phone":"202222"},{"id":"50","latitute":"50","longitude":"100","number_phone":"50"},{"id":"110","latitute":"50","longitude":"50","number_phone":"110"},{"id":"120","latitute":"27","longitude":"31","number_phone":"120"},{"id":"130","latitute":"28","longitude":"29","number_phone":"120"},{"id":"140","latitute":"30","longitude":"40","number_phone":"140"},{"id":"800","latitute":"60","longitude":"30","number_phone":"800"},{"id":"353629054230064","latitute":"70","longitude":"80","number_phone":"120"}]}
Please help!
U can use the JsonReader class.
try (JsonReader in = Json.createReader(r)) {
JsonObject jsonObject= in.readObject();
YourObject obj = new YourObject();
obj.setSomething(jsonObject.getString("something", null));
// "something" is the key in the json file, null is the default
// when "something" was not found
} catch (JsonException | ClassCastException ex) {
throw new BadRequestException("Invalid Json Input");
}
you can use the Google Library GSON as well, it is easy to use and self explaining.
https://code.google.com/p/google-gson/
Gson Goals
Provide simple toJson() and fromJson() methods to convert Java objects to JSON and vice-versa
Allow pre-existing unmodifiable objects to be converted to and from JSON
Extensive support of Java Generics
Allow custom representations for objects
Support arbitrarily complex objects (with deep inheritance hierarchies and extensive use of generic types)
I want to parse the some data from this page:
http://www.bbc.co.uk/radio1/programmes/schedules/england/2013/03/1.json
The data I want to parse is the titles however I am unsure how I can extract the data. This is what I have done so far:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public class Test
{
public Test() { }
public static void main(String[] args)
{
URL url;
HttpURLConnection connection = null;
InputStream is = null;
JSONParser parser = new JSONParser();
try
{
url = new URL("http://www.bbc.co.uk/radio1/programmes/schedules/england/2013/03/1.json");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
is = connection.getInputStream();
BufferedReader theReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String reply;
while ((reply = theReader.readLine()) != null)
{
System.out.println(reply);
Object obj = parser.parse(reply);
JSONObject jsonObject = (JSONObject) obj;
String title = (String) jsonObject.get("time");
System.out.println(title);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
This just returns null. Can anybody tell me what I need to change? Thanks.
If you read the javadoc of JSONObject#get(String) which is actually HashMap.get(String), it states
Returns: the value to which the specified key is mapped, or null if
this map contains no mapping for the key
Your JSON does not contain a mapping for the key time.
Edit:
If you meant title instead of time, take this extract of the JSON
{"schedule":{"service":{"type":"radio","key":"radio1","title":"BBC Radio 1",...
You need to first get schedule as a JSONObject, then service as a JSONObject, and then title as a normal String value. Apply this differently depending on the type of JSON value.
use something like JSONGen to better understand your data structures, maybe even map your data to the generated objects using google-gson library
I have a list of links, containing links to html and xml pages, how can I extract the xml links from the list? in java
thanks
You could use a list of common filename extensions to divine the type of data stored at a given URL, but that often won't be very reliable, particularly with Web 2.0 sites (just look at the URL of this SO question itself). In addition, a link to a PHP script (.php) or other dynamic content site could return either HTML or XML. Or it could return something else entirely, such as a JPG file.
There are a lot of simple heuristics you can use for detecting HTML vs. XML, simply by looking at the beginning of the file. For example, you could look for the <!DOCTYPE ...> declaration, check for the <?xml ...?> directive, and check to see if the file contains a root <html> tag. Of course, these should all be case-insensitive checks.
You can also try to identify the type of file based on its MIME type (for example, text/html or text/xml). Unfortunately, many servers return incorrect or invalid MIME types, so you often have to read the beginning of the file anyway to divine its content, as you can see in my first two inadequate versions of a getMimeType() method below. The third attempt worked better, but the third-party MimeMagic library still provided disappointing results. Nevertheless, you could use the additional heuristics that I mentioned earlier to either replace or improve the getMimeType() method.
package com.example.mimetype;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicException;
import net.sf.jmimemagic.MagicMatchNotFoundException;
import net.sf.jmimemagic.MagicParseException;
public class MimeUtils {
// After calling this method, you can retrieve a list of URLs for each mimetype.
public static Map<String, List<String>> sortLinksByMimeType(List<String> links) {
Map<String, List<String>> mapMimeTypesToLinks = new HashMap<String, List<String>>();
for (String url : links) {
try {
String mimetype = getMimeType(url);
System.out.println(url + " has mimetype " + mimetype);
// If this mimetype hasn't already been initialized, initialize it.
if (! mapMimeTypesToLinks.containsKey(mimetype)) {
mapMimeTypesToLinks.put(mimetype, new ArrayList<String>());
}
List<String> lst = mapMimeTypesToLinks.get(mimetype);
lst.add(url);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return mapMimeTypesToLinks;
}
public static String getMimeType(String url) throws MalformedURLException, IOException, MagicParseException, MagicMatchNotFoundException, MagicException {
// first attempt at determining MIME type--returned null for all URLs that I tried
// FileNameMap filenameMap = URLConnection.getFileNameMap();
// return filenameMap.getContentTypeFor(url);
// second attempt at determining MIME type--worked better, but still returned null for many URLs
// URLConnection c = new URL(url).openConnection();
// InputStream in = c.getInputStream();
// String mimetype = URLConnection.guessContentTypeFromStream(in);
// in.close();
// return mimetype;
URLConnection c = new URL(url).openConnection();
BufferedInputStream in = new BufferedInputStream(c.getInputStream());
byte[] content = new byte[100];
in.read(content);
in.close();
return Magic.getMagicMatch(content, false).getMimeType();
}
public static void main(String[] args) {
List<String> links = new ArrayList<String>();
links.add("http://stackoverflow.com/questions/10082568/how-to-differentiate-xml-from-html-links-in-java");
links.add("http://stackoverflow.com");
links.add("http://stackoverflow.com/feeds");
links.add("http://amazon.com");
links.add("http://google.com");
sortLinksByMimeType(links);
}
}
I'm not certain if your links are some sort of Link object, but as long as you can access the value as a string this should work I think.
List<String> xmlLinks = new ArrayList<String>();
for (String link : list) {
if (link.endsWith(".xml") || link.contains(".xml")) {
xmlLinks.add(link);
}
}