fill array from json file without knowing the keys - java

I have the following Json file and I want to create list of array ,i don't know the keys name (like person ,lastname etc ) it can be
many entities like employes users etc but the structure of the file must be exactly the same ,how can i do that ?
the file is
{
"Person": [
{
"name": "Peter",
"lastname": "ta",
"age": 43,
"sex": "male"
},
{
"name": "Zara",
"lastname": "treg",
"age": 25,
"sex": "female"
}
]
}
what I need is to create list of array like this
person ,name,peter ,lastname,ta,age,43,sex,male
person ,name,zara ,lastname,treg,age,23,sex,female
....
I started with the following code to get the file but since i dont know the name of the keys I dont know how to proceed.
JSONObject jsonObject= (JSONObject) parser.parse(new FileReader("C:\\General\\jsonperson.txt"));

You can use
String[] keyNames= JSONObject.getNames(jsonObject);
to get the names of the keys.
Javadoc
Using this, you can get the values using getJSONObject
Looping these you can construct the array you are looking for.

Check Example 4 on this page: https://code.google.com/p/json-simple/wiki/DecodingExamples
Specifically, this part:
Map json = (Map)parser.parse(jsonText, containerFactory);
Iterator iter = json.entrySet().iterator();
System.out.println("==iterate result==");
while(iter.hasNext()){
Map.Entry entry = (Map.Entry)iter.next();
System.out.println(entry.getKey() + "=>" + entry.getValue());
}
System.out.println("==toJSONString()==");
System.out.println(JSONValue.toJSONString(json));
That's how you might iterate over the entries of a JSONObject. By the way, with this library, if it's the one I think you're using, a JSONObject is just a java.util.Map, and you can use all of its methods - that's why it works for this example to cast the parse result to a Map.
All of the JSON <-> Java object mappings for this lib: https://code.google.com/p/json-simple/wiki/MappingBetweenJSONAndJavaEntities

You can also try the below code:
public void performExecute() throws IOException {
JsonFactory jsonFactory = new JsonFactory();
ObjectMapper objectMapper = new ObjectMapper(jsonFactory);
File file = new File("json.txt");
TypeReference<HashMap<String, Object>> typeReference = new TypeReference<HashMap<String, Object>>() {};
HashMap<String, Object> jsonMap = objectMapper.readValue(file, typeReference);
System.out.println("JSON DATA: " + jsonMap);
}
Make sure the Jackson library is in your class path & you imports the following classes while using the code:
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

Related

Java Jackson: get number of all subelements [duplicate]

This question already has answers here:
Java Stream API - count items of a nested list
(3 answers)
Closed 11 months ago.
I have the following piece of JSON code:
{
"films": [{
"id": "12345",
"title": "The Fellowship Of The Ring",
"year": 2001,
"cast": [{
"actor": "Billy Boyd",
"id": "770911234",
"character": "Peregrin Took"
},
{
"actor": "Ian McKellen",
"id": "162659743",
"character": "Gandalf"
}
]
},
{
"id": "67890",
"title": "Spiderman",
"year": 2021,
"cast": [{
"actor": "Tom Holland",
"id": "162660329",
"character": "Spiderman"
}]
}
]
}
I'm fairly new to using Jackson and now would like to know, what would be the best way to get the number of all actors of all film objects with Java? Would it be to parse it from the movies object or to make a separate parsing method?
I have created a JsonFilm POJO that contains the fields of a film object and a class JsonFilms with getter+setter:
public class JsonFilms {
#JsonProperty("films")
private List<JsonFilms > jsonFilmList = new ArrayList<>();
public List<JsonFilm> getFilmsList() {
return Collections.unmodifiableList(jsonFilmList );
}
public void setFilmsList(List<JsonFilm> jsonFilmList ) {
this.jsonFilmList = jsonFilmList;
}
}
With an ObjectMapper, I can retrieve all films:
File jsonFile = new File(filePath);
JsonFilms jsonFilmList = objectMapper.readValue(jsonFile, JsonFilms.class);
Well, you can create appropriate classes such as Film and Actor and parse your Json into appropriate structure of your classes, or you can do it quick and dirty and parse it into a Map<String, Object>. Your map will contain just one key "films" which will contain a List<Map<String, Object>>. You should iterate through that list and from each Map<String, Object> in that list extract a key "cast" that will contain a List<Map<String, Object>>. You summarize the lengths of all of those lists and that's your answer. In order to convert your JSON string into your Map<String, Object> you can use Jackson library, and in particular ObjectMapper class and its method readValue() or you can use an Open-source library MgntUtils that provides class JsonUtils which is a wrapper over Jackson library anyway. With that class parsing your Json String would look like this:
Map<String, Object> myMap = null;
try {
myMap = JsonUtils.readObjectFromJsonString(jsonString, Map.class);
}
} catch (IOException e) {
...
}
The Maven artifacts for MgntUtils library could be found here, and library as a jar along with Javadoc and source code could be found on Github here
If you just want the titles and actors' names, you can use ObjectMapper.readTree(). Since JsonNode implements Iterable, you can stream all value nodes using StreamSupport.stream(node.spliterator(), false).
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
Map<String, List<String>> filmActors = StreamSupport
.stream(root.get("films").spliterator(), false)
.collect(Collectors.toMap(
filmNode -> filmNode.get("title").asText(),
filmNode -> StreamSupport
.stream(filmNode.get("cast").spliterator(), false)
.map(castNode -> castNode.get("actor").asText())
.toList()));
filmActors.forEach((title, actors) -> System.out.println(title + ": "
+ actors.stream().collect(Collectors.joining(", "))));
Output:
The Fellowship Of The Ring: Billy Boyd, Ian McKellen
Spiderman: Tom Holland
If you're allowed to add new libraries then the JsonPath library could help. The simplest code would be:
import com.jayway.jsonpath.JsonPath;
import net.minidev.json.JSONArray;
...
JSONArray result = JsonPath.read(json, "$.films[*].cast[*].actor");
System.out.println("there are " + result.size() + " actors");
System.out.println("they are:");
result.forEach(System.out::println);

How can this type of response handled in android?

I am getting the response like this from Api. In which locationSector is fixed key but the inside key may exist or not and corresponding the key value as well.
this is json string.
How can I store this in hashmap also the inner value can also be stored in hash map like.
HashMap<String, HashMap<String,List<String>>>
"locationSector": {
"Adampur": [
"Adampur",
"Agroha",
"Anaj Mandi",
"Auto Market",
"Bhadu Colony",
"Chulibagrian"
],
"Allahabad": [
"Allahabad"
],
"Gurgaon":[
"Dlf 1",
"Dlf 2"
]
}
try this out if you're using org.json library:
import com.fasterxml.jackson.databind.ObjectMapper;
Map<String, Object> response = new ObjectMapper().readValue(str, HashMap.class);
str = youre json String.
Simple as this, if you want a studentId,
String studentIds = response.get("student id").toString();

Splitting a Json to multiple Json String in Java efficiently

I have a json String like below and I want to split/explode it in to multiple json string.
input:
{
"name": "paddy",
"age": 29,
"cities": [
{
"cityName": "Chennai",
"year": "2013-2015"
},
{
"cityName": "Bangalore",
"year": "2015-2019"
}
]
}
And I want to convert in to two Json string
json 1
{
"name": "paddy",
"age": 29,
"cities": [
{
"cityName": "Chennai",
"year": "2013-2015"
}
]
}
json 2
{
"name": "paddy",
"age": 29,
"cities": [
{
"cityName": "Bangalore",
"year": "2015-2019"
}
]
}
As of now, my approach below using jackson library.
package com.test;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class JsonParser {
public static void main(String[] args) throws IOException {
String json =
"{\n"
+ "\t\"name\": \"paddy\",\n"
+ "\t\"age\": 29,\n"
+ "\t\"cities\": [\n"
+ "\t\t{\n"
+ "\t\t\t\"cityName\": \"Chennai\",\n"
+ "\t\t\t\"year\": \"2013-2015\"\n"
+ "\t\t},\n"
+ "\t\t{\n"
+ "\t\t\t\"cityName\": \"Bangalore\",\n"
+ "\t\t\t\"year\": \"2015-2019\"\n"
+ "\t\t}\n"
+ "\t]\n"
+ "}";
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// Create a list to store the result (the list will store Jackson tree model objects)
List<JsonNode> result = new ArrayList<>();
JsonNode tree = mapper.readTree(json);
JsonNode paths = tree.get("cities");
Iterator<JsonNode> elements = paths.elements();
while (elements.hasNext()) {
JsonNode path = elements.next();
// Create a copy of the tree
JsonNode copyOfTree = mapper.valueToTree(tree);
((ArrayNode)copyOfTree.get("cities")).removeAll().add(path);
// Add the modified tree to the result list
result.add(copyOfTree);
}
// Print the result
for (JsonNode node : result) {
System.out.println(mapper.writeValueAsString(node));
System.out.println();
}
}
}
This above approach can work fine if the json is smaller. Is there any better approach to handle large json files. For example, assume the "cities" have million objects.
Thanks.
There is many different factors you need to consider. First, do not copy the whole root object. In case, you have a big cities array you just waste a memory for creating new copy and remove all elements from it. See below example:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;
public class JsonApp {
public static void main(String[] args) throws IOException {
File jsonFile = new File("./spring-basics/src/main/resources/test.json");
ObjectMapper mapper = new ObjectMapper();
// read whole JSON
ObjectNode root = (ObjectNode) mapper.readTree(jsonFile);
String citiesFieldName = "cities";
// remove cities from root, now it contains only common properties
ArrayNode cities = (ArrayNode) root.remove(citiesFieldName);
cities.elements().forEachRemaining(item -> {
// copy root
ObjectNode copyOfRoot = root.deepCopy();
// add one city to copy
copyOfRoot.set(citiesFieldName, copyOfRoot.arrayNode().add(item));
// add to result or send further
System.out.println(copyOfRoot);
});
}
}
Above code copies root and adds one element to cities array. Now, we need to think what to do with result. You can send it immediately for next processing or store in list and send it in bulk operation. Another improvement could be splitting cities arrays on bigger chunks, more than 1 element. See this article, how to split list. For example, in case you have 1_000_000 elements, split it on list of 1_000 elements chunks.

json mapper writerWithDefaultPrettyPrinter for multiple json objects separated by new line

I had multi line json Strings separated by new line character. I am using jackson version 1.9.13 For example
{"name":"firstPerson","age":25,"gender":"male"}\n
{"name":"secondPerson","age":30,"gender":"male"}\n
{"name":"thirdPerson","age":25,"gender":"male"}\n
...............
The delimiter may be \n\r or \n based on the operating system using. Basically it is a batch record processing where we save all the contents back to database . But we also save the entire request as well .
My requirement is to get the multiple lines of json object when i use in prettyprint format.Please find the code
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
public class Main {
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, JsonParseException, IOException {
//mapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
//mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
String json = "{\"name\":\"firstPerson\",\"age\":25,\"gender\":\"male\"}\n{\"name\":\"secondPerson\",\"age\":30,\"gender\":\"male\"}\n{\"name\":\"thirdPerson\",\"age\":25,\"gender\":\"male\"}";
System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectMapper.readValue(json, Object.class)));
System.out.println(json);
}
}
The out put is :
{
"name" : "firstPerson",
"age" : 25,
"gender" : "male"
}
But i want to display as :
{
"name" : "secondPerson",
"age" : 30,
"gender" : "male"
}
{
"name" : "thirdPerson",
"age" : 25,
"gender" : "male"
}
{
"name" : "firstPerson",
"age" : 25,
"gender" : "male"
}
I know its not a standard way of json string. json string always enclosed in flower brasis . But as it is already existing system i dont want to break the system to change the code . It can be done simply using any of the string handling functions in java but i need to use jackson and jackson's pretty printer.
Is there a way to get this done ?
Thanks,
Eresh
Your json string is made of 3 JSON objects, so you need to format them one at the time and then concatenate them:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
String json = "{\"name\":\"firstPerson\",\"age\":25,\"gender\":\"male\"}\n{\"name\":\"secondPerson\",\"age\":30,\"gender\":\"male\"}\n{\"name\":\"thirdPerson\",\"age\":25,\"gender\":\"male\"}";
String[] jsons = json.split("\n");
String output = "";
for (String str : jsons) {
output += objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectMapper.readValue(str, Object.class)) + "\n";
}
System.out.println(output);
String person= "{\"name\":\"firstPerson\",\"age\":25,\"gender\":\"male\"}\n{\"name\":\"secondPerson\",\"age\":30,\"gender\":\"male\"}\n{\"name\":\"thirdPerson\",\"age\":25,\"gender\":\"male\"}";
Object json = mapper.readValue(person, Object.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json));
Just like:
On demand
ObjectMapper objectMapper = new ObjectMapper();
Object obj = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectMapper.readValue(stringValue, Object.class));
For older version replace writerWithDefaultPrettyPrinter() with defaultPrettyPrinterWriter()
Globally
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
Object obj = objectMapper.writeValueAsString(objectMapper.readValue(stringValue, Object.class));

How to parse this JSON with GSON?

I'am struggling with a problem to parse a JSON with GSON which contains lists as values. This should be pretty simple, but I can't figure out how to solve it. The JSON is:
{
"key1": [
"foo1",
"foo2",
"foo3"
],
"key2": [
"foo4",
"foo5",
"foo6"
],
"key3": [
"foo7",
"foo8",
"foo9"
]
}
I think the best way is to put it into a Map<String, List<String>>, but I can't create a Type for it. Like:
Type jsonArrayType = new TypeToken<Map<String, List<String>>>(){}.getType();
// Doesn't work, causes exception: "com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.List"
Thanks for any help!
You will get a java.lang.reflect.Type from the getType() method. Use that to parse your json. Here is a small working example (Java 7)
String json = "{\"key1\": [\"foo1\",\"foo2\",\"foo3\"],\"key2\": [\"foo4\",\"foo5\",\"foo6\"],\"key3\": [\"foo7\",\"foo8\",\"foo9\"]}";
java.lang.reflect.Type type = new TypeToken<Map<String, List<String>>>(){}.getType();
Map<String, List<String>> map = new Gson().fromJson(json, type);
System.out.println(map);
This snippet prints the below value
{key1=[foo1, foo2, foo3], key2=[foo4, foo5, foo6], key3=[foo7, foo8, foo9]}

Categories