Create JSON/GSON from json file within a jar - json

I use Google's GSON library to generate GSON/JSON objects.
However, now I have the problem that I need to create a GSON object for a file within a jar.
I can get a InputStream, BufferedReader or Properties from the json file I want to parse to an GSON object, however the Gson().toJson() then Gson().fromJson can't generate a GSON object from any of the above mentioned.
So, how would I access a json file within a jar and pass it to the GSON library to get a GSON file?
Right now I have something along this line:
public class Main {
public static void main(String[] args) throws IOException {
JarFile jar;
jar = new JarFile("path.jar");
InputStream inputStream = jar.getInputStream(jar.getEntry("file.json"));
}

Related

How to directly convert MongoDB Document do Jackson JsonNode in Java

I would like to store a MongoDB Document (org.bson.Document) as a Jackson JsonNode file type. There is a outdated answer to this problem here, inspired by this I was able to succesfully parse the Document with
ObjectMapper mapper = new ObjectMapper();
...
JonNode jsonData = mapper.readTree(someBsonDocument.toJson());
In my understanding this will:
Convert the Document to string
Parse the string and create a JsonNode object
I noticed there is some support for MongoDB/BSON for the Jackson Project - jackson-datatype-mongo and BSON for Jackson, but I can not figure out how to use them to do the conversion more efficiently.
I was able to figure-out some solution using bson4jackson:
public static InputStream documentToInputStream(final Document document) {
BasicOutputBuffer outputBuffer = new BasicOutputBuffer();
BsonBinaryWriter writer = new BsonBinaryWriter(outputBuffer);
new DocumentCodec().encode(writer, document, EncoderContext.builder().isEncodingCollectibleDocument(true).build());
return new ByteArrayInputStream(outputBuffer.toByteArray());
}
public static JsonNode documentToJsonNode(final Document document) throws IOException {
ObjectMapper mapper = new ObjectMapper(new BsonFactory());
InputStream is = documentToInputStream(document);
return mapper.readTree(is);
}
I am not sure if this is the most efficient way, I am assuming it is still better solution than converting BSOn to String and parsing that string. There is an open Ticket in the mongoDB JIRA for adding conversion from Document, DBObject and BsonDocument to toBson and vice versa, which would simplify the whole process a lot.
Appreciate this isn't what the OP asked for - but might be helpful to some. I've managed to do this in reverse using MongoJack. The key thing is to use the JacksonEncoder which can turn any Json-like object into a Bson object. Then use BsonDocumentWriter to write it to a BsonDocument instance.
#Test
public void writeBsonDocument() throws IOException {
JsonNode jsonNode = new ObjectMapper().readTree("{\"wibble\": \"wobble\"}");
BsonDocument document = new BsonDocument();
BsonDocumentWriter writer = new BsonDocumentWriter(document);
JacksonEncoder transcoder =
new JacksonEncoder(JsonNode.class, null, new ObjectMapper(), UuidRepresentation.UNSPECIFIED);
var context = EncoderContext.builder().isEncodingCollectibleDocument(true).build();
transcoder.encode(writer,jsonNode,context);
Assertions.assertThat(document.toJson()).isEqualTo("{\"wibble\": \"wobble\"}");
}

Nested JSON with root element not having key and it is varying

I have a unique requirement where i need to construct a JSON as below.
{
"XXXMonitoring/DC/EVN/DBNAME":{
"t":123456777,
"s":{
"CAPTURE":{
"c":100
}
}
}
}
where the root element "XXXMonitoring/DC/EVN/DBNAME" contains "/" in between as it represents a path. I tried with GSON to have nested java but not sure how i can represent "XXXMonitoring/DC/EVN/DBNAME" from my Java object.
Can someone help me on this.
I'm not sure if this is what are you asking...
But sollidus (/) is escaped by backslash (\) to be sure that the browser won’t mistake it for the closing script tag
when you need to use that key, you can remove backslash with String.replaceAll() method
json.toString().replaceAll("\\\\", "");
The JSON string can be constructed without POJO class using the below code.
If the JSON structure is same and only values will change for the keys, you can replace the hard coded values with variables and convert this into an utility method. The utility method can be reused to generate the JSON string.
public static void main(String[] args) throws IOException {
Gson gson = new Gson();
JsonObject jsonRootObject = new JsonObject();
JsonObject jsonFirstLevelObject = new JsonObject();
// t property
jsonFirstLevelObject.addProperty("t", 123456777);
JsonObject jsonCaptureObject = new JsonObject();
JsonObject jsonCObject = new JsonObject();
jsonCObject.addProperty("c", 100);
jsonCaptureObject.add("CAPTURE", jsonCObject);
// s property
jsonFirstLevelObject.add("s", jsonCaptureObject);
jsonRootObject.add("XXXMonitoring/DC/EVN/DBNAME", jsonFirstLevelObject);
System.out.println(gson.toJson(jsonRootObject));
}
I have a library called GsonPath which might suit your needs. The aim of the library is to provide an annotation processor that generates the boilerplate code to help simplify the POJO you need to write.
By using the library you can write a POJO similar to the following:
#AutoGsonAdapter(rootField = "XXXMonitoring/DC/EVN/DBNAME")
public class SamplePojo {
int t;
#SerializedName("s.CAPTURE.c")
int sCapture;
}
Then all you need to do in your gson object is to register a special TypeAdapterFactory
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapterFactory(GsonPath.createTypeAdapterFactory());
Gson gson = builder.create();
The documentation within the library is faily comprehensive, let me know if you have any problems!

JAXB Namespace issue

This question is for Mr.Blaise Doughan on JAXB Namespace
I have situation where,
Have a sample.xsd (old version - no namespace ). Generated JAXB classes using the XJC for the same XSD file. I got one example that uses the JAXB classes to unmarshal the XML data file , based on the XSD.
The sample.xsd file got changed (new version - added namespace). Again generated JAXB classes using the XJC for the new XSD file. The Example is updated so that it can now work for new XSD file
Now I got a situation , where iam getting XML data file based on old XSD and I would like to use the updated example file to unmarshal the old XML data.
One solution I could see , generating two object factory one with namespace and one without namespace. Can we do that? if so I can use the appropriate Object factory based on the my XML data I get.
Or would like to know , how can I generate JAXB classes for both XSD files , but XJC is not generating , it shows error - No changes detected in schema or binding files - skipping source generation.
Can I create a wrapper over the new Object Factory so that it can handle both ?
Please do provide me with some solution so that I can unmarshal the old file with new JAXB classes. Can
Apply a Namespace
In the case where the input XML does not have a namespace you can leverage a SAX XMLFilter to apply a namespace.
import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;
public class NamespaceFilter extends XMLFilterImpl {
private static final String NAMESPACE = "http://www.example.com/customer";
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(NAMESPACE, localName, qName);
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
super.startElement(NAMESPACE, localName, qName, atts);
}
}
Do the Unmarshal
The unmarshalling is done leveraging JAXB's UnmarshallerHandler as the ContentHandler
import javax.xml.bind.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
public class Demo {
public static void main(String[] args) throws Exception {
// Create the JAXBContext
JAXBContext jc = JAXBContext.newInstance(Customer.class);
// Create the XMLFilter
XMLFilter filter = new NamespaceFilter();
// Set the parent XMLReader on the XMLFilter
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
filter.setParent(xr);
// Set UnmarshallerHandler as ContentHandler on XMLFilter
Unmarshaller unmarshaller = jc.createUnmarshaller();
UnmarshallerHandler unmarshallerHandler = unmarshaller
.getUnmarshallerHandler();
filter.setContentHandler(unmarshallerHandler);
// Parse the XML
InputSource xml = new InputSource("src/blog/namespace/sax/input.xml");
filter.parse(xml);
Customer customer = (Customer) unmarshallerHandler.getResult();
// Marshal the Customer object back to XML
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
}
For More Information
http://blog.bdoughan.com/2012/11/applying-namespace-during-jaxb-unmarshal.html

How to read a CSV file from Hdfs?

I have my Data in a CSV file. I want to read the CSV file which is in HDFS.
Can anyone help me with the code??
I'm new to hadoop. Thanks in Advance.
The classes required for this are FileSystem, FSDataInputStream and Path. Client should be something like this :
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
conf.addResource(new Path("/hadoop/projects/hadoop-1.0.4/conf/core-site.xml"));
conf.addResource(new Path("/hadoop/projects/hadoop-1.0.4/conf/hdfs-site.xml"));
FileSystem fs = FileSystem.get(conf);
FSDataInputStream inputStream = fs.open(new Path("/path/to/input/file"));
System.out.println(inputStream.readChar());
}
FSDataInputStream has several read methods. Choose the one which suits your needs.
If it is MR, it's even easier :
public static class YourMapper extends
Mapper<LongWritable, Text, Your_Wish, Your_Wish> {
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
//Framework does the reading for you...
String line = value.toString(); //line contains one line of your csv file.
//do your processing here
....................
....................
context.write(Your_Wish, Your_Wish);
}
}
}
If you want to use mapreduce you can use TextInputFormat to read line by line and parse each line in mapper's map function.
Other option is to develop (or find developed) CSV input format for reading data from file.
There is one old tutorial here http://hadoop.apache.org/docs/r0.18.3/mapred_tutorial.html but logic is same in new versions
If you are using single process for reading data from file it is same as reading file from any other file system. There is nice example here https://sites.google.com/site/hadoopandhive/home/hadoop-how-to-read-a-file-from-hdfs
HTH

How do I convert a POJO to JSON in PlayN?

I want to send a string with json content to a REST service. How can I convert a simple POJO to a json string? Normaly I would use Gson to do this:
My class that I want to convert:
public class UserMdl {
String name;
String pwHash;
//Constructur, getter and setter....
}
And my code to do this:
UserMdl userMd = new UserMdl("name", "pwHash");
Gson gson = new Gson();
String json = gson.toJson(userMdl);
However I cannot get gson to work with PlayN in the HTML build. It only works in the Java build. And I cannot figure out how to do this with the PlayN.json() stuff.