I have a file with several JSON objects, each of which may contain other objects and arrays.
I would like to deserialize this, preferably using the Jackson library, into a data structure that maintains top-level object separation, e.g. an array or a list of Java HashMap<String, String> objects, where each HashMap will contain the data of a single top-level JSON object from the file.
From what I have seen, you can't get a HashMap<String, String> from Jackson, so I have to put up with a HashMap<String, Object>:
List<HashMap<String,Object>> values = new ObjectMapper().readValue(new BufferedReader(new FileReader(path)), new TypeReference<List<HashMap<String, Object>>>() {});
The deserialization above works as expected, however I get all the file data and a not a single JSON object's data, as I would like.
Any ideas?
Thanks!
After quite a bit of effort, here is a simple approach that seems to work:
Reader inputReader = new BufferedReader(new FileReader(filename));
int readEvents = 0;
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createJsonParser(inputReader);
JsonToken token = null;
ObjectMapper mapper = new ObjectMapper();
HashMap<String,Object> attributes = null;
ArrayList<Map<String,Object>> matchedEvents = new ArrayList<Map<String,Object>>();
try
{
while ((token=parser.nextToken()) != null)
{
if (token == JsonToken.START_OBJECT)
{
readEvents++;
attributes = mapper.readValue(parser,
new TypeReference<HashMap<String, Object>>() {});
if (attributes != null)
{
matchedEvents.add(attributes);
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("Read " + readEvents + " events");
Each of the HashMap<String, Object> objects placed in the above ArrayList corresponds to a single (top-level) JSON event.
The readValue() methods apparently do not return a Map(String, String) object.
Related
I have a method that exports every POJO person and create an array into a JSON:
Node temp = testa;
ObjectMapper mapper = new ObjectMapper();
FileWriter fileWriter = new FileWriter(Paths.get("jPerson.json").toFile(), true);
SequenceWriter seqWriter = mapper.writer().writeValuesAsArray(fileWriter);
while (temp != null) {
seqWriter.write(temp.getPersona());
temp = temp.getSuccessivo();
}
seqWriter.close();
I want to create a method that read every object of the array and print it on the screen. This is the prototype, but it prints the hashcode (Person#6a1aab78, etc.):
ObjectMapper mapper = new ObjectMapper();
try {
Persona[] pJson;
pJson = mapper.readValue(Paths.get("jPersona.json").toFile(), Persona[].class);
System.out.println(ReflectionToStringBuilder.toString(pJson));
} catch (IOException e) {
e.printStackTrace();
}
ReflectionToStringBuilder.toString(Object) doesn't create a "deep" toString method. In your case you could just call Arrays.toString(pJson) and it would have the same result.
Easiest solution is to just override toString in Persona.
public class Persona {
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
System.out.println(Arrays.toString(pJson));
Or you use a Stream to join all the values in the pJson array to one String.
System.out.println('[' + Arrays.stream(pJson)
.map(ReflectionToStringBuilder::toString)
.collect(Collectors.joining(", "))+']');
You can do it with ObjectMapper.
ObjectMapper mapper = new ObjectMapper();
// pretty print
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(pJson);
System.out.println(json);
Reference: https://mkyong.com/java/how-to-enable-pretty-print-json-output-jackson/
If you want to print your POJO Persona as JSON, you can use Jackson's ObjectMapper to serialize to a JsonNode and use JsonNode#toString():
final Persona persona = ...;
final JsonNode json = objectMapper.readValue(persona, JsonNode.class);
System.out.println(json);
If you want to print multiple Persona objects, you can iterate:
for(final Persona persona : personas) {
final JsonNode json = objectMapper.readValue(persona, JsonNode.class);
System.out.println(json);
}
or, even better, serialize once and iterate:
final Persona[] personas = ...;
final JsonNode jsonArray = objectMapper.valueToTree(personas);
// Check may not be necessary.
if(json.isArray()) {
// JsonNode implements Iterable.
for(final JsonNode jsonNode : jsonArray) {
System.out.println(jsonNode);
}
}
I am getting a json from rest call as {"d1":1, "d2":1, "d3":0, "d4":1} which is stored in db as - {d1=1, d2=1, d3=0, d4=1}.
When I am reading from database i am getting the above as string as - {d1=1, d2=1, d3=0, d4=1}. I want to convert this to its original form as before like - {"d1":1, "d2":1, "d3":0, "d4":1} mentioned above.
How can i achieve this in java. is there any json library available to do this ?
Sofar I have tried this but it didn't worked out -
JSONParser parser = new JSONParser();
JSONObject json = (JSONObject) parser.parse(jsonString);
I want to put this json in ResponseEntity>.
Even I tried -
jsonString = jsonString.replaceAll("=", ":");
JSONObject jsonObject = new JSONObject(jsonString);
String finalJsonString = jsonObject.toString();
This is giving back response as "{\"d1\":1, \"d2\":1, \"d3\":0, \"d4\":1}" with double quotes in the begining and ending with backslashes before double quotes for keys.
The String returned through DB is not in JSON format, so parsing fails.
You could use the following approach to format the returned string into a JSON string, and then parse it.
I have used Guava's Splitter.MapSplitter:
String in = "{d1=1,d2=1,d3=0,d4=1}";
in = in.replaceAll("[{}]", "");
Map<String, String> properties = Splitter.on(",").withKeyValueSeparator("=").split(in);
JSONObject obj = new JSONObject(properties);
String formattedString = obj.toString();
The string that you are retrieving from DB is a Map data structure. So you can convert a Map to JSON as follows:
Map<String,String> payload = new HashMap<>();
payload.put("key1","value1");
payload.put("key2","value2");
String json = new ObjectMapper().writeValueAsString(payload);
System.out.println(json);
Edited
The following code snippet will provide you the complete JSON response.
#RestController
#RequestMapping("/api/v1/")
public class TestController {
#GetMapping(value="test",produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> test() {
Map<String,String> payload = new HashMap<>();
payload.put("d1","value1");
payload.put("d2","value2");
payload.put("d3","value3");
payload.put("d4","value4");
String json =null;
try {
json= new ObjectMapper().writeValueAsString(payload);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return new ResponseEntity(json,HttpStatus.OK);
}
}
Postman test:
You can do as follows :
ObjectMapper mapper = new ObjectMapper();
try {
MyResponse result = mapper.readValue(e.getResponseBodyAsString(),MyResponse.class);
return result;
} catch (IOException e1) {
e1.printStackTrace();
}
I have a hashmap with a String key and String value. It contains a large number of keys and their respective values.
For example:
key | value
abc | aabbcc
def | ddeeff
I would like to write this hashmap to a csv file such that my csv file contains rows as below:
abc,aabbcc
def,ddeeff
I tried the following example here using the supercsv library: http://javafascination.blogspot.com/2009/07/csv-write-using-java.html. However, in this example, you have to create a hashmap for each row that you want to add to your csv file. I have a large number of key value pairs which means that several hashmaps, with each containing data for one row need to be created. I would like to know if there is a more optimized approach that can be used for this use case.
Using the Jackson API, Map or List of Map could be written in CSV file. See complete example here
/**
* #param listOfMap
* #param writer
* #throws IOException
*/
public static void csvWriter(List<HashMap<String, String>> listOfMap, Writer writer) throws IOException {
CsvSchema schema = null;
CsvSchema.Builder schemaBuilder = CsvSchema.builder();
if (listOfMap != null && !listOfMap.isEmpty()) {
for (String col : listOfMap.get(0).keySet()) {
schemaBuilder.addColumn(col);
}
schema = schemaBuilder.build().withLineSeparator(System.lineSeparator()).withHeader();
}
CsvMapper mapper = new CsvMapper();
mapper.writer(schema).writeValues(writer).writeAll(listOfMap);
writer.flush();
}
Something like this should do the trick:
String eol = System.getProperty("line.separator");
try (Writer writer = new FileWriter("somefile.csv")) {
for (Map.Entry<String, String> entry : myHashMap.entrySet()) {
writer.append(entry.getKey())
.append(',')
.append(entry.getValue())
.append(eol);
}
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
As your question is asking how to do this using Super CSV, I thought I'd chime in (as a maintainer of the project).
I initially thought you could just iterate over the map's entry set using CsvBeanWriter and a name mapping array of "key", "value", but this doesn't work because HashMap's internal implementation doesn't allow reflection to get the key/value.
So your only option is to use CsvListWriter as follows. At least this way you don't have to worry about escaping CSV (every other example here just joins with commas...aaarrggh!):
#Test
public void writeHashMapToCsv() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("abc", "aabbcc");
map.put("def", "ddeeff");
StringWriter output = new StringWriter();
try (ICsvListWriter listWriter = new CsvListWriter(output,
CsvPreference.STANDARD_PREFERENCE)){
for (Map.Entry<String, String> entry : map.entrySet()){
listWriter.write(entry.getKey(), entry.getValue());
}
}
System.out.println(output);
}
Output:
abc,aabbcc
def,ddeeff
Map<String, String> csvMap = new TreeMap<>();
csvMap.put("Hotel Name", hotelDetails.getHotelName());
csvMap.put("Hotel Classification", hotelDetails.getClassOfHotel());
csvMap.put("Number of Rooms", hotelDetails.getNumberOfRooms());
csvMap.put("Hotel Address", hotelDetails.getAddress());
// specified by filepath
File file = new File(fileLocation + hotelDetails.getHotelName() + ".csv");
// create FileWriter object with file as parameter
FileWriter outputfile = new FileWriter(file);
String[] header = csvMap.keySet().toArray(new String[csvMap.size()]);
String[] dataSet = csvMap.values().toArray(new String[csvMap.size()]);
// create CSVWriter object filewriter object as parameter
CSVWriter writer = new CSVWriter(outputfile);
// adding data to csv
writer.writeNext(header);
writer.writeNext(dataSet);
// closing writer connection
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
If you have a single hashmap it is just a few lines of code. Something like this:
Map<String,String> myMap = new HashMap<>();
myMap.put("foo", "bar");
myMap.put("baz", "foobar");
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, String> kvp : myMap.entrySet()) {
builder.append(kvp.getKey());
builder.append(",");
builder.append(kvp.getValue());
builder.append("\r\n");
}
String content = builder.toString().trim();
System.out.println(content);
//use your prefered method to write content to a file - for example Apache FileUtils.writeStringToFile(...) instead of syso.
result would be
foo,bar
baz,foobar
My Java is a little limited but couldn't you just loop over the HashMap and add each entry to a string?
// m = your HashMap
StringBuilder builder = new StringBuilder();
for(Entry<String, String> e : m.entrySet())
{
String key = e.getKey();
String value = e.getValue();
builder.append(key);
builder.append(',');
builder.append(value);
builder.append(System.getProperty("line.separator"));
}
string result = builder.toString();
How can i convert JSON string to format given below and back to JSON string.
List<Map<String, String>> variables =new ArrayList<>();
I tried searching for this. Only thing which i could find is converting list to array and then to string. But using
TypeA[] array = a.toArray(new TypeA[a.size()]);
does not seems feasible here.
Converting List<Map<String,String>> to JSON string :
public String listmap_to_json_string(List<Map<String, String>> list)
{
JSONArray json_arr=new JSONArray();
for (Map<String, String> map : list) {
JSONObject json_obj=new JSONObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
try {
json_obj.put(key,value);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
json_arr.put(json_obj);
}
return json_arr.toString();
}
Or simply using google gson library:
public String listmap_to_json_string(List<Map<String, String>> list){
// Use toJson method to serialize list to Json
return new GsonBuilder().setPrettyPrinting().create().toJson(list);
}
Converting JSON string to List<Map<String,String>>:
public List<Map<String, String>> json_string_to_listmap(String json){
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<Map<String, String>>>() {}.getType();
// Use fromJson method to deserialize json into an ArrayList of Map
return gson.fromJson(json , type);
}
For more informations check this link.
Indeed you should update your question to give more details. Meanwhile, with the current understanding I have from your post I would suggest you to look at ObjectMapper class from org.codehaus.jackson.map.
You will easily get a JSON converted in the type you want by using
// string in json format
String json;
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(json, TypeA.class);
This code show how convert json string to type List<Map<String,String>>:
ObjectMapper objectMapper = new ObjectMapper();
try {
TypeReference < List < Map < String, String >>> typeReference = new TypeReference < List < Map < String, String >>> () {
};
List < Map < String, String >> res = objectMapper.readValue("[{\"size\":\"100x200\"}]", typeReference);
System.out.println("type: " + typeReference.getType());
for (Map < String, String > map: res) {
for (String key: map.keySet()) {
System.out.println(key + " : " + map.get(key));
}
}
} catch (IOException e) {
e.printStackTrace();
}
I used cURL to get some twitter feeds in the form of a json file ("twitter-feed.json"). I want to convert this json file to a JSONArray object. How do I do it?
I am new to Java and json. Your suggestions are most welcome.
FileInputStream infile = new FileInputStream("input/twitter-feed.json");
// parse JSON
JSONArray jsonArray = new JSONArray(string);
// use
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
System.out.println(jsonObject.getString("id"));
System.out.println(jsonObject.getString("text"));
System.out.println(jsonObject.getString("created_at"));
}
Thanks,
PD.
You need to read the file first, convert it to String then feed it to the JSONArray (I am assuming that you are using the JSON-Java Project. The code below illustrates how to read the file and set it to JSONArray
// read the source file, source comes from streaming API delimited by newline
// done by curl https://stream.twitter.com/1/statuses/sample.json?delimited=newline -utwitterUsername:twitterPasswd
// > /Projects/StackOverflow/src/so7655570/twitter.json
FileReader f = new FileReader("/Projects/StackOverflow/src/so7655570/twitter.json");
BufferedReader br = new BufferedReader(f);
ArrayList jsonObjectArray = new ArrayList();
String currentJSONString = "";
// read the file, since I ask for newline separation, it's easier for BufferedReader
// to separate each String
while( (currentJSONString = br.readLine()) != null ) {
// create new JSONObject
JSONObject currentObject = new JSONObject(currentJSONString);
// there are more than one way to do this, right now what I am doing is adding
// each JSONObject to an ArrayList
jsonObjectArray.add(currentObject);
}
for (int i = 0; i < jsonObjectArray.size(); i++) {
JSONObject jsonObject = jsonObjectArray.get(i);
// check if it has valid ID as delete won't have one
// sample of JSON for delete :
// {"delete":{"status":{"user_id_str":"50269460","id_str":"121202089660661760","id":121202089660661760,"user_id":50269460}}}
if(jsonObject.has("id")) {
System.out.println(jsonObject.getInt("id"));
System.out.println(jsonObject.getString("text"));
System.out.println(jsonObject.getString("created_at") + "\n");
}
}
Steps explanation :
Stream API does not provide valid JSON as a whole but rather a valid one specified by the delimited field. Which is why, you can't just parse the entire result as is.
In order to parse the JSON, I use the delimited to use newline since BufferedReader has a method readLine that we could directly use to get each JSONObject
Once I get each valid JSON from each line, I create JSONObject and add it to the ArrayList
I then iterate each JSONObject in the ArrayList and print out the result. Note that if you want to use the result immediately and don't have the need to use it later, you can do the processing itself in while loop without storing them in the ArrayList which change the code to:
// read the source file, source comes from streaming API
// done by curl https://stream.twitter.com/1/statuses/sample.json?delimited=newline -utwitterUsername:twitterPasswd
// > /Projects/StackOverflow/src/so7655570/twitter.json
FileReader f = new FileReader("/Projects/StackOverflow/src/so7655570/twitter.json");
BufferedReader br = new BufferedReader(f);
String currentJSONString = "";
// read the file, since I ask for newline separation, it's easier for BufferedReader
// to separate each String
while( (currentJSONString = br.readLine()) != null ) {
// create new JSONObject
JSONObject currentObject = new JSONObject(currentJSONString);
// check if it has valid ID as delete status won't have one
if(currentObject.has("id")) {
System.out.println(currentObject.getInt("id"));
System.out.println(currentObject.getString("text"));
System.out.println(currentObject.getString("created_at") + "\n");
}
}
You may try Gson:
For just arrays you can use:
Gson gson = new Gson();
//(Deserialization)
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
To deserialize an array of objects, you can just do:
Container container = new Gson().fromJson(json, Container.class);
As shown here
Use ObjectMapper Class from jackson library like this :
//JSON from file to Object
Staff obj = mapper.readValue(new File("c:\\file.json"), Staff.class);
//JSON from URL to Object
Staff obj = mapper.readValue(new URL("http://mkyong.com/api/staff.json"), Staff.class);
//JSON from String to Object
Staff obj = mapper.readValue(jsonInString, Staff.class);