Java to JSON (w/ nested elements) - java

I am trying to create a JSON representation out of a this java object. I am using Jackson.
private List<Map<String, String>> Crews = new ArrayList<Map<String, String>>();
public Crew() {
Map<String, String> crew1 = new HashMap<String, String>();
crew1.put("crewId", "3");
crew1.put("crewName", "T.I.P.");
crew1.put("crewIntro", "Teamwork Is Perfect");
crew1.put("crewGenre", "bboy");
crew1.put("crewAsso", "TIP Studio");
crew1.put("crewLeaderContact", "tip.tip.com");
Crews.add( crew1 );
Map<String, String> crew2 = new HashMap<String, String>();
crew2.put("crewId", "4");
crew2.put("crewName", "Pinky Chicks");
crew2.put("crewIntro", "Best feminine males");
crew2.put("crewGenre", "Girl's hip-hop");
crew2.put("crewAsso", "JBlack Studio");
crew2.put("crewLeaderContact", "jblack#jblack.com");
Crews.add( crew2 );
}
public List<Map<String, String>> getCrews() {
return Crews;
}
public void setCrews(List<Map<String, String>> crews) {
Crews = crews;
}
public static void createCrewJSON(String filePath) {
Crew crew = new Crew();
ObjectMapper mapper = new ObjectMapper();
try {
mapper.writeValue(new File(filePath), crew.getCrews());
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("JSON Crew File Created");
}
}
These are my result:
[
{
"crewIntro":"Teamwork Is Perfect",
"crewId":"3",
"crewGenre":"bboy","crewName":"T.I.P.",
"crewLeaderContact":"tip.tip.com",
"crewAsso":"TIP Studio"
},
{
"crewIntro":"Best feminine males",
"crewId":"4",
"crewGenre":"Girl's hip-hop",
"crewName":"Pinky Chicks",
"crewLeaderContact":"jblack#jblack.com",
"crewAsso":"JBlack Studio"
}
]
How would I change my createCrewJSON method to produce this: ?
{
"Crews": [
{
"Crew": {
"crewIntro":"Teamwork Is Perfect",
"crewId":"3",
"crewGenre":"bboy","crewName":"T.I.P.",
"crewLeaderContact":"tip.tip.com",
"crewAsso":"TIP Studio"
}
},
{
"Crew": {
"crewIntro":"Best feminine males",
"crewId":"4",
"crewGenre":"Girl's hip-hop",
"crewName":"Pinky Chicks",
"crewLeaderContact":"jblack#jblack.com",
"crewAsso":"JBlack Studio"
}
}
]
}
I've done multiple searches on Google for generating these nested structures, but I only get JSON to Java results..

create pojo something like
public class Crews{
private List<Map<String, String>> crews;
// gettes ,setters
}
create object for this class. and set crews and parse this object

Related

Thread safety of static ArrayList in Java

I have a nested json like below. From this I want to get specific values which are not again json objects. e.g. values against keys "first_name" or "last_name" or "purpose" etc
[
{
"purpose":"Audit",
"sender_name":"Tester One",
"sent_date":"10-10-2020",
"approval":true,
"agency":{
"name":"Test Agency",
"id":1234
},
"records":[
{
"students":{
"first_name":"FirstOne",
"last_name":"LastOne",
"address":{
"street":"123 Street",
"city":"Test City",
"zip":12345
}
},
"employees":{
"first_name":"EmpFirst",
"last_name":"EmpLast",
"address":{
"street":"ABC Street",
"city":"ABC City",
"zip":99921
}
}
}
],
"completion":true
}
]
For this I wrote 2 recursive methods and another method which will invoke this method. Following is my code.
public class JsonUtils {
private static ArrayList<Object> resultSet = new ArrayList<Object>();
/*Method to convert json to Map*/
public static Map<String, Object> convertJsonArrayToMap(String filePath) {
List<Object> list = null;
ObjectMapper mapper = new ObjectMapper();
try {
list = mapper.readValue(new File(filePath), new TypeReference<List<Object>>() {
});
} catch (IOException e) {
e.printStackTrace();
}
Map<String, Object> data = (Map<String, Object>) list.get(0);
return data;
}
/*Method to iterate nested HashMap*/
public static Object jsonMapIterator(Map<String, Object> map, String key) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
jsonMapIterator((Map<String, Object>) entry.getValue(), key);
} else if (entry.getValue() instanceof ArrayList) {
jsonListIterator((ArrayList<Object>) entry.getValue(), key);
} else {
if (entry.getKey() == key) resultSet.add(entry.getValue());
}
}
return resultSet!=null?resultSet:null;
}
/*Method to iterate array list of objects*/
public static Object jsonListIterator(ArrayList<Object> list, String key) {
AtomicReference<Object> value = null;
Consumer<Object> action = i -> {
if (i instanceof ArrayList) {
jsonListIterator((ArrayList<Object>) i, key);
} else if (i instanceof Map) {
jsonMapIterator((Map<String, Object>) i, key);
} else {
value.set(i);
}
};
list.stream().forEach(action);
return value;
}
/*method to invoke recursive search and return all values for any given key*/
public static Object jsonValueFetcher(Map<String, Object> jsonData, String key){
resultSet.clear();
ArrayList<Object> values;
values = (ArrayList<Object>) jsonMapIterator(jsonData, key);
return values.size()==0?null:values;
}
public static void main(String[] args) {
Map<String, Object> jsonData = convertJsonArrayToMap("src/test/resources/nestedJson.json");
System.out.println(jsonValueFetcher(jsonData,"first_name"));
}
}
Now in here, how can I make the static variable resultSet and the two recursive methods thread safe in case of a parallel test execution?

Create, Write, Edit JSON file in Android Studio

I would like to create a JSON file in the internal storage of the phone, to store data.
I want to be able to add objects ("configX") to the file and then read the data.
It should look something like this:
{
"config1": {
"component1": "url",
"component2": "url",
"component3": "url"
},
"config2": {
"component1": "url",
"component2": "url",
"component3": "url"
}
}
I can create a JSON file like this :
public void saveToJson(){
JSONObject json = new JSONObject();
try {
json.put("component1", "url");
json.put("component2", "url");
String jsonString = json.toString();
FileOutputStream fos = this.openFileOutput("jsonfile", Context.MODE_PRIVATE);
fos.write(jsonString.getBytes());
fos.close();
Log.d("JSON" , json.toString());
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
But how to put the components in the config object ? And how to retrieve the data ?
EDIT 1 :
https://stackoverflow.com/a/62474912/11652860
Thanks for the very detailed answer, I'm doing something wrong. I have an Activity where I put and save data to the json file:
public class Data {
private Map<String, Map<String, String>> map;
public Data() {
}
public Data(Map<String, Map<String, String>> map) {
this.map = map;
}
public Map<String, Map<String, String>> getMap() {
return map;
}
public void setMap(Map<String, Map<String, String>> map) {
this.map = map;
}
}
Map<String, String> config1 = new HashMap<>();
config1.put("component1", "url1");
config1.put("component2", "url1");
config1.put("component3", "url1");
Map<String, Map<String, String>> map = new HashMap<>();
map.put("config1", config1);
Data data = new Data(map);
Gson gson = new Gson();
String json = gson.toJson(data);
FileOutputStream fos = null;
try {
fos = webViewActivity.this.openFileOutput("jsonfile", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fos.write(json.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
And a fragment where I load the data :
public class Data {
private Map<String, Map<String, String>> map;
public Data() {
}
public Data(Map<String, Map<String, String>> map) {
this.map = map;
}
public Map<String, Map<String, String>> getMap() {
return map;
}
public void setMap(Map<String, Map<String, String>> map) {
this.map = map;
}
}
public void load(){
FileInputStream fis = null;
try {
fis = getContext().openFileInput("jsonfile.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String text;
while ((text = br.readLine()) != null){
sb.append(text).append("\n");
Gson gson = new Gson();
String json = gson.toJson(text);
Data data = gson.fromJson(json, Data.class);
String url = data.getMap().get("config1").get("component1");
frameTV.setText(url);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The saving and loading parts must be wrong, but they worked for getting text out a text file
EDIT 2 :
I found the problem, I wasn't loading and saving properly :
SAVING:
String filename = "jsonfile.txt";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(json.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
LOADING :
FileInputStream fis = getContext().openFileInput("jsonfile.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
String json = sb.toString();
Gson gson = new Gson();
Data data = gson.fromJson(json, Data.class);
String priceURL = data.getMap().get("config1").get("url1");
EDIT 3 :
My problem now is that I need to create the file once and then check if the file exists, if it does I need to check if config1 exists if it doesn't I need to put config in the file.
But I can't check if config1 exists because I get : java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Map com.a.app.ui.app.appFragment$Data.getMap()
I check if it exists by doing :
Boolean configTest = data.getMap().containsKey("config1");
if(!configTest){}
How can I create the file and check the data without getting a NullPointerException ?
Thank you for helping me !
Google's Gson library will be helpful in this case.
Add dependency for Google Gson in your radle file.
dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
}
Create a class for your data container
public class Data {
private Map<String, Map<String, String>> map;
public Data() {
}
public Data(Map<String, Map<String, String>> map) {
this.map = map;
}
public Map<String, Map<String, String>> getMap() {
return map;
}
public void setMap(Map<String, Map<String, String>> map) {
this.map = map;
}
}
Add data to your class
Map<String, String> config1 = new HashMap<>();
config1.put("component1", "url1");
config1.put("component2", "url1");
config1.put("component3", "url1");
Map<String, String> config2 = new HashMap<>();
config2.put("component1", "url1");
config2.put("component2", "url1");
config2.put("component3", "url1");
Map<String, Map<String, String>> map = new HashMap<>();
map.put("config1", config1);
map.put("config2", config2);
Data data = new Data(map);
Get gson from data class
Gson gson = new Gson();
String json = gson.toJson(data);
You can now save this json in a file in a text format.
Now when reading, load the content of the text file in a String say 'jsonString'.
Deserialize the jsonString to Java Object
Data data = gson.fromJson(json, Data.class);
Access configurations
String url = data.getMap().get("config1").get("component1");
Add new configurations
Map<String, String> config3 = new HashMap<>();
config3.put("component1", "url1");
config3.put("component2", "url1");
config3.put("component3", "url1");
data.getMap().put("config3", config3);
Follow again these steps to save configs
Or You can manually edit the text file to add configs according to the predefined format.
{
"maps":{
"config2":{
"component1":"url1",
"component2":"url1",
"component3":"url1"
},
"config1":{
"component1":"url1",
"component2":"url1",
"component3":"url1"
}
}
}
This is how you create multiple Objects in a single JSON object:
//Creating first Object
JSONObject config1 = new JSONObject();
try {
json.put("component1", "url");
json.put("component2", "url");
json.put("component2", "url");
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Creating second object
JSONObject config2 = new JSONObject();
try {
json.put("component1", "url");
json.put("component2", "url");
json.put("component2", "url");
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject finalJSON = new JSONObject();
try {
//Adding both objects in one single object
json.put("config1", config1);
json.put("config2", config2);
String jsonString = finalJSON.toString();
FileOutputStream fos = this.openFileOutput("jsonfile", Context.MODE_PRIVATE);
fos.write(jsonString.getBytes());
fos.close();
Log.d("JSON" , json.toString());
} catch (IOException | JSONException e) {
e.printStackTrace();
}
This will give you the desired output. Also, if in case you want to make any object an array, you can use JSONArray for that.
Please consider using https://github.com/google/gson. You will be working with class instance rather than with JSONObject. Much more convenient.
Just to give you the idea of what you can do:
public class TestClass {
private final Map<String, String> config1;
private final Map<String, String> config2;
public TestClass(Map<String, String> config1, Map<String, String> config2) {
this.config1 = config1;
this.config2 = config2;
}
}
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Map<String, String> config1 = new HashMap<String, String>();
config1.put("hello1.1", "world1.1");
config1.put("hello1.2", "world1.2");
Map<String, String> config2 = new HashMap<String, String>();
config2.put("hello2.1", "world2.1");
config2.put("hello2.2", "world2.2");
TestClass testClass = new TestClass(config1, config2);
Log.d("zzz", gson.toJson(testClass));
The above prints:
{
"config1": {
"hello1.1": "world1.1",
"hello1.2": "world1.2"
},
"config2": {
"hello2.1": "world2.1",
"hello2.2": "world2.2"
}
}
You can go back and force between json string and the entity itself. To edit, you only need to work with object - natural and convenient way.

How to use JSON with difficult objects

I have problem with dynamic JSON data. I don't know how to put it into my JAVA class. I need "routes" data. But i don't know what i should do with this ""2019-05-27": {...".
It is part of JSON file...
{
"2019-05-26": {
"lastUpdate": "2019-05-26 06:05:02",
"routes": [
{
"routeId": 107,
"agencyId": 18
},
{
"routeId": 222,
"agencyId": 22
}
]
},
"2019-05-27": {
"lastUpdate": "2019-05-27 06:05:02",
"routes": [
{
"routeId": 33,
"agencyId": 14
},
{
"routeId": 345,
"agencyId": 2232
}
]
}
}
The code below doesn't work. It is not Map<String,Map<String, String>>. I think it is -
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String,Map<String, String>>>() {}.getType();
Map<String,Map<String, String>> map = null;
try {
map = gson.fromJson(new FileReader("routes.json"), mapType);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
What should I do to take this data ?
Create POJO classes like that :
public class MyObject {
private List<Route> routes;
private String lastUpdate;
public MyObject(List<Route> routes, String lastUpdate) {
this.routes = routes;
this.lastUpdate = lastUpdate;
}
// assume getters and setters
}
public class Route {
private String routeId;
private String agencyId;
public Route(String routeId, String agencyId) {
this.routeId = routeId;
this.agencyId = agencyId;
}
// assume getters and setters
}
To test it :
public static void main(String[] args) throws IOException {
Gson gson = new Gson();
String json = Files.lines(Paths.get("src/main/resources/data.json")).collect(Collectors.joining());
Type mapType = new TypeToken<Map<String, MyObject>>() {}.getType();
Map<String, MyObject> map = gson.fromJson(json, mapType);
map.forEach((s, myObject) -> System.out.println(s + " " + myObject.getLastUpdate()));
}
The output is :
2019-05-26 2019-05-26 06:05:02
2019-05-27 2019-05-27 06:05:02
You just need to create a map which has date as a key and custom object as value.
Please check this line :
json = Files.lines(Paths.get("routes.json")).collect(Collectors.joining());
this line may store null value and that's why you are getting a java.lang.NullPointerException.
Please check this by debugging. I think you will get the solution.

Java Nashorn build json array object in java can't find way

I try to create java json array ,
can't find any way to create them using Nashorn
i can create simple objects ...
private void createJsonObject() {
try {
final Map<String, Object> newMap = new HashMap<>();
newMap.put("foo",1);
newMap.put("bar", true);
ScriptObjectMirror json = (ScriptObjectMirror) this.engine.eval("JSON");
json.putAll(newMap);
this.engine.put("jsonObject", json);
String result = (String) this.engine.eval("JSON.stringify(jsonObject)");
System.out.println(result);
} catch (ScriptException e) {
e.printStackTrace();
}
}
Result : {"bar":true,"foo":1}
Here i try to create array but im getting empty json
private void createJsonObject() {
try {
List<String> returnList = new ArrayList<>();
returnList.add("x");
returnList.add("y");
ScriptObjectMirror json = (ScriptObjectMirror) this.engine.eval("JSON");
json.put("test",returnList);
this.engine.put("jsonObject", json);
String result = (String) this.engine.eval("JSON.stringify(jsonObject)");
System.out.println(result);
} catch (ScriptException e) {
e.printStackTrace();
}
}
Result: {}
The end goal is to build array of objects in memory using java native tools without using dependencies

Incompatible Type Error in Android Project

This is an Android project. I'm completely new to Java (just started learning). As stated in the title, I'm getting an Incompatible Type Error
I've attached the respective method here :
public void init(Map map) {
this.productIds = new ArrayList();
try {
if (map.containsKey("products")) {
for (Entry<String, Object> "//Error Lies here" entry : ((HashMap) map.get("products")).entrySet()) {
InAppProduct productId = new InAppProduct();
productId.productId = ((String) entry.getKey()).toLowerCase();
HashMap<String, Object> extraValues = (HashMap) entry.getValue();
if (extraValues.containsKey(ShareConstants.MEDIA_TYPE)) {
productId.productType = (String) extraValues.get(ShareConstants.MEDIA_TYPE);
}
if (extraValues.containsKey("days")) {
productId.days = ((Integer) extraValues.get("days")).intValue();
}
this.productIds.add(productId);
}
return;
}
this.productIds = new ArrayList(ConfigurationFetcher.this.mDefaultsDelegate.getDefaultsInAppPackages());
} catch (Exception e) {
e.printStackTrace();
}
}
The Error is :
Required Object but found Entry <String, Object>
Let me know if you need additional code or any details. Thank You.
Set is a generic type. It is a container that can contain any kind of object.
In your case, it seems that your Set contains Map.Entry<String, Object> objects but since you don't specify that anywhere, Java assumes your Set contains Objects (the Java class that all other classes derive from) and produces an Incompatible Type Error.
Here's a slightly altered version of your code that should work.
public void init(Map map) {
this.productIds = new ArrayList();
try {
if (map.containsKey("products")) {
// ***** We now specify the type of object that the Set contains.
Set<Map.Entry<String, Object>> entrySet = ((HashMap) hm.get("products")).entrySet();
for (Entry<String, Object> entry : entrySet) {
InAppProduct productId = new InAppProduct();
productId.productId = ((String) entry.getKey()).toLowerCase();
HashMap<String, Object> extraValues = (HashMap) entry.getValue();
if (extraValues.containsKey(ShareConstants.MEDIA_TYPE)) {
productId.productType = (String) extraValues.get(ShareConstants.MEDIA_TYPE);
}
if (extraValues.containsKey("days")) {
productId.days = ((Integer) extraValues.get("days")).intValue();
}
this.productIds.add(productId);
}
return;
}
this.productIds = new ArrayList(ConfigurationFetcher.this.mDefaultsDelegate.getDefaultsInAppPackages());
} catch (Exception e) {
e.printStackTrace();
}
}
map.get("products")).entrySet() is a set of products, each product is a Object, not Entry <String, Object>.
This should work:
public void init(Map map) {
this.productIds = new ArrayList();
try {
if (map.containsKey("products")) {
for (Object entry : ((HashMap) map.get("products")).entrySet()) {
InAppProduct productId = new InAppProduct();
productId.productId = ((String) entry.getKey()).toLowerCase();
HashMap<String, Object> extraValues = (HashMap) entry.getValue();
if (extraValues.containsKey(ShareConstants.MEDIA_TYPE)) {
productId.productType = (String) extraValues.get(ShareConstants.MEDIA_TYPE);
}
if (extraValues.containsKey("days")) {
productId.days = ((Integer) extraValues.get("days")).intValue();
}
this.productIds.add(productId);
}
return;
}
this.productIds = new ArrayList(ConfigurationFetcher.this.mDefaultsDelegate.getDefaultsInAppPackages());
} catch (Exception e) {
e.printStackTrace();
}
}

Categories