I want to convert from xml to json in java and get an output.
But whike doing so only some parts from the xml are getting converted and not the whole xml.
Any help
My input xml is :
<?xml version="1.0" encoding="UTF-8"?>
<important-data certified="true" processed="true">
<timestamp>232423423423</timestamp>
<authors>
<author>
<firstName>Tim</firstName>
<lastName>Leary</lastName>
</author>
</authors>
<title>Flashbacks</title>
<shippingWeight>1.4 pounds</shippingWeight>
<isbn>978-0874778700</isbn>
</important-data>
And my code is:
package com.discursive.answers;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import net.sf.json.JSON;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import net.sf.json.xml.XMLSerializer;
import org.json.XML;
public class ConvertXMLtoJSON {
public static int PRETTY_PRINT_INDENT_FACTOR = 4;
public static String TEST_XML_STRING = "<?xml version=\"1.0\" ?>" +
"<test attrib=\"moretest\">" +
"Turn this to JSON</test>";
public static void main(String[] args) {
new ConvertXMLtoJSON();
}
public ConvertXMLtoJSON() {
try {
InputStream is = ConvertXMLtoJSON.class.getResourceAsStream("sample-xml.xml");
if (is != null) {
String xml = IOUtils.toString(is);
JSON json = XMLSerializer.readObject(xml);
System.out.println(json.toString().split(",").length);
for(int i= 0 ;i < json.toString().split(",").length; i ++)
System.out.println(json.toString().split(",")[i]);
} else {
System.out.println("Checkpoint 1");
}
} catch (java.io.IOException ioe) {
ioe.printStackTrace();
}
}
Applying the above mentioned xml and code I get the output as:
{"timestamp":"232423423423"
"authors":"\n\t\t\n\t\t\tTim\n\t\t\tLeary\n\t\t\n\t"
"title":"Flashbacks"
"isbn":"978-0874778700"
"shippingWeight":"1.4 pounds"}
where as it should be as :
{
"#certified": "true",
"#processed": "true",
"timestamp": "232423423423",
"authors": [ {
"firstName": "Tim",
"lastName": "Leary"
}],
"title":
"Flashbacks",
"shippingWeight": "1.4 pounds",
"isbn": "978-0874778700"
}
What changes should I do to get the required output?
The article How to Convert XML to JSON in Java gives the same example as yours using json-lib.
The code in the example works, so it might be worth checking the versions on your libs. The json-lib website lists the required libs.
I managed to get mine working with the following libs on my build path:
commons-beanutils-1.8.3
commons-collections-3.2.1
commons-io-1.2
commons-lang-2.4
commons-logging-1.1.3
ezmorph-1.0.6
json-lib2.4-jdk15
xom-1.2.10
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");
Wanted to covert an xml String to Json and I am doing it as below.
XML which has to be converted
<Item>
<Property name="Description" value="Description 1"/>
<Property name="EffDate" value="01/05/2017"/>
<Property name="ExpDate" value="12/31/9999"/>
<Property name="Status" value="Launched"/>
</Item>
I have created a Class for the xml as below.
public class Context {
#XmlElement(name = "Item")
private List<Item> offer;
}
public class Item {
#XmlElement(name = "Property")
private List<Property> properties;
}
public class Property {
#XmlAttribute
private String name;
#XmlAttribute
private String value;
}
I am using Gson libraries to convert this Java object to Json - g.toJson.
Comverted JSON -
"offer": [{
"properties": [{
"name": "Description",
"value": "Description 1"
},
{
"name": "EffDate",
"value": "01/05/2017"
},
{
"name": "ExpDate",
"value": "12/31/9999"
},
{
"name": "Status",
"value": "Launched"
}]
}]
But we wanted to convert the JSON as below -
"offer": [{
"Description" : "Description 1",
"EffDate":"01/05/2017",
"ExpDate": "12/31/9999",
"Status": "Launched"
}]
Is there a way to convert the properties name and value as Item class properties.?
Try using this link: https://github.com/stleary/JSON-java This is a JSON Helper class that can convert XML to JSON for example:
public class Main {
public static int PRETTY_PRINT_INDENT_FACTOR = 4;
public static String TEST_XML_STRING =
"<?xml version=\"1.0\" ?><test attrib=\"moretest\">Turn this to JSON</test>";
public static void main(String[] args) {
try {
JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
String jsonPrettyPrintString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
System.out.println(jsonPrettyPrintString);
} catch (JSONException je) {
System.out.println(je.toString());
}
}
}
Hope this helps :)
It is possible using FasterXML library. where you can write your custom logic for generating XML and JSON. By overriding serialize of JsonSerializer class.
Need to write Serializer like :
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class ContextSerializer extends JsonSerializer<Context> {
#Override
public void serialize(Context t, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
jg.writeStartObject();
jg.writeArrayFieldStart("offer");
for (Item i : t.offer) {
jg.writeStartObject();
for (Property property : i.properties) {
jg.writeStringField(property.name, property.value);
}
jg.writeEndObject();
}
jg.writeEndArray();
jg.writeEndObject();
}
}
For convert:
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBException;
public class Main {
public static void main(String[] args) throws JAXBException, JsonProcessingException {
Context c = new Context();
List<Item> offer = new ArrayList<>();
Item pr = new Item();
pr.properties = new ArrayList<>();
Property p = new Property();
p.name = "asdf";
p.value = "va1";
pr.properties.add(p);
p = new Property();
p.name = "asdf1";
p.value = "va11";
pr.properties.add(p);
offer.add(pr);
c.offer = offer;
try {
SimpleModule module = new SimpleModule();
module.addSerializer(Context.class, new ContextSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(Include.NON_DEFAULT);
String json = objectMapper.writeValueAsString(c);
System.out.println(json);
} catch (Exception e) {
System.out.println(""+e);
}
}
}
O/P JSON : (Provided O/P JSON is wrong in your question if you give the name to the list("offer") then it always inside object link)
{
"offer": [{
"asdf": "va1",
"asdf1": "va11"
}
]
}
Maven Dependency for package is:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0.pr3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0.pr3</version>
</dependency>
If you are using Java 8 or later, you should check out my open source library: unXml. unXml basically maps from Xpaths to Json-attributes.
It's available on Maven Central.
Example
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.nerdforge.unxml.factory.ParsingFactory;
import com.nerdforge.unxml.parsers.Parser;
import org.w3c.dom.Document;
public class Parser {
public ObjectNode parseXml(String xml){
Parsing parsing = ParsingFactory.getInstance().create();
Document document = parsing.xml().document(xml);
Parser<ObjectNode> parser = parsing.obj("/")
.attribute("offer", parsing.arr("/Item")
.attribute("Description", "Property[#name='Description']/#value")
.attribute("EffDate", "Property[#name='EffDate']/#value")
.attribute("ExpDate", "Property[#name='ExpDate']/#value")
.attribute("Status", "Property[#name='Status']/#value")
)
.build();
ObjectNode result = parser.apply(document);
return result;
}
}
It will return a Jackson ObjectNode, with the following json:
{
"offer": [
{
"Status": "Launched",
"Description": "Description 1",
"ExpDate": "12/31/9999",
"EffDate": "01/05/2017"
}
]
}
You may convert xml to a map, modify it and then convert to a json. Underscore-java library has static methods U.fromXml(xml) and U.toJson(json). I am the maintainer of the project.
I've been writing a Rest service using Jackson to extract the name and sizeFromStorage inside the response value.
I created the below classes in an attempt to do this:
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(value = {"status", "header"})
public class Vaults {
private List<Object> response;
public Vaults(){
}
public Vaults(List<Object> response){
this.response = response;
}
public List<Object> getResponse(){
return response;
}
public void setResponse(List<Object> response) {
this.response = response;
}
#Override
public String toString() {
return "" + response;
}
}
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.InputStream;
public class JacksonObjectModelTest {
public static void main(String[] args) throws IOException {
String jsonFileName = "/JsonRead/json.json";
List<Vaults> emps = new JacksonObjectModelTest().getVaultList(jsonFileName);
System.out.println(emps.toString());
}
public ArrayList<Vaults> getVaultList(String jsonFileName) throws IOException {
//read json file data to String
InputStream inputStream = getClass().getResourceAsStream(jsonFileName);
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
//convert json string to object
CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, Vaults.class);
ArrayList<Vaults> emps = objectMapper.readValue(inputStream, collectionType);
return (ArrayList<Vaults>) emps;
}
}
{
"status": "ok",
"header": {
"now": 1491545894581,
"status": "ok",
"requestId": "WOcvJsCoAmoAAESbkBYAAAB5"
},
"response": {
"vault": [
{
"id": 20,
"name": "Apple",
"description": "",
"sizeFromStorage": 95957225298,
"storagePools": [
{
"storagePool": {
"id": 1,
"name": "storage-pool1",
"sizeFromStorage": 95957225298,
"generations": [
{
"generation": {
"sequence": 0
}
}
]
}
}
]
},
{
"id": 21,
"name": "Banana",
"description": "",
"sizeFromStorage": 98957268244,
"storagePools": [
{
"storagePool": {
"id": 2,
"name": "storage-pool1",
"sizeFromStorage": 98957268244,
"generations": [
{
"generation": {
"sequence": 0
}
}
]
}
}
]
},
]
}
}
The output I get from this is:
[[{vaults=[{id=20, name=Apple, description=, sizeFromStorage=95957225298, storagePools=[{storagePool={id=1, name=storage-pool1, sizeFromStorage=5043, estimateUsableTotalLogicalSizeFromStorage=95957225298, generations=[{generation={sequence=0}}]}}]}, {id=20, name=Apple, description=, sizeFromStorage=95957225298, storagePools=[{storagePool={id=1, name=storage-pool1, sizeFromStorage=5043, estimateUsableTotalLogicalSizeFromStorage=95957225298, generations=[{generation={sequence=0}}]}}]}]]
However, what I want to do is the name and sizeFromStorage values. So far I've managed to strip out the first three values. Unfortunately I'm now stuck as I'm not very familiar with Rest services or reading JSON. Is there any way I can delve further into the JSON to get what I need or have I approached this in the wrong way?
Additional info:
Since posting my original question I came up with this(based on something I saw on a different site):
package JsonRead;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTreeModel {
public static void main(String[] args) {
try{
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(new File("JsonRead/json.json"));
JsonNode vaultsNode = root.path("response").path("vault");
/*if(vaultsNode.isArray()){
for(JsonNode node : vaultsNode){
String name = node.path("name").asText();
System.out.println("Array Name: " + name);
}
}*/
for(JsonNode node : vaultsNode){
String name = node.path("name").asText();
String bytesUsed = node.path("sizeFromStorage").asText();
System.out.println("Name: " + name + ", Bytes Used: " + bytesUsed);
}
} catch(IOException e){
System.out.println("IO Exception " + e );
}
}
}
It works for what I want but is there a better way to do this?
Will, thanks for the response. I'll look into your suggestion.
Ok, so i just re-read your question.
Recommend creating yourself a VaultDAO object with a more meaningful custom object type to use for the response collections. Prvoided you use the same variable names (which it looks like are known to you) then it should deserialize for you
below is my java code to read from a json file
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class FileIO {
#SuppressWarnings("unchecked")
//public static Showtime [] movie = MoviesListing.movie();
public void importTxt() {
int j = 0;
JSONParser parser = new JSONParser();
try {
JSONArray a = (JSONArray) parser.parse(new FileReader("C:/Users/Glambert/Dropbox/java/New folder/perfection/UPdate/json.txt"));
for (Object o : a)
{
JSONObject person = (JSONObject) o;
MoviesListing.movie[j].assign((String) person.get("moviename"));
MoviesListing.movie[j].assignShowingStatus((String) person.get("showingstatus"));
MoviesListing.movie[j].assignSynopsis((String) person.get("synopsis"));
MoviesListing.movie[j].assignDirector((String) person.get("director"));
MoviesListing.movie[j].assignCast((String) person.get("cast"));
MoviesListing.movie[j].assignReviewerRate((double) person.get("reviewerRate"));
MoviesListing.movie[j].assignPastReviews((String) person.get("pastreviews"));
MoviesListing.movie[j].assignMovieRating((String) person.get("movierating"));
MoviesListing.movie[j].assignShowtimes((JSONArray) person.get("showtimes"));
j++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
It works from reading a json file like this:
[
{
"moviename":"Goosebumps",
"showingstatus":"Now Showing",
"synopsis":"Upset...",
"director":"Rob Letterman",
"cast":"Jack Black, Dylan Minnette, Odeya Rush, Amy Ryan",
"reviewerRate": 3.2 ,
"pastreviews":"Goosebumps...",
"movierating":"PG",
"showtimes":[
"09.30",
"12.30"
],
"job":"Teacher"
},
{
"moviename":"Bridge of Spies",
"showingstatus":"Now Showing",
"synopsis":"Tom Hanks stars..",
"director":"Steven Spielberg",
"cast":"Tom Hanks, Mark Rylance",
"reviewerRate": 3.9,
"pastreviews":"JBridge...",
"movierating":"PG-13",
"showtimes":[
"09.40",
"10.45"
],
}
]
However, I want to write/edit into the txt file in the same, or at least close to this format. Anyone knows how to do that?
In the JSON format you have provided, remove the comma after last array:
....
"showtimes":[
"09.40",
"10.45"
]
}
]
Solution:
You can use (Download the Jar file from Maven)
http://mvnrepository.com/artifact/com.google.code.gson/gson
And Create a Bean for Your Data as below:
MovieBean.java
private String moviename;
private String showingstatus;
...
private ArrayList<Double> showtimes;
private String job;
And After that you can use,
Gson methods fromJson and toJson for creating JSON to Bean and Bean to JSON respectively.
You can edit the data in Bean and save it again on the same content file.
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.