map() with JSON array - java

Not Looking for Jackson Solution.
List of Imports:
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.util.List;
import java.util.stream.Collectors;
JSON data:
{
"Name": "ABC.com",
"Developer": "Vishwa ratna",
"Project List": [
"Compnay: National",
"Compnay: Enterprise",
"Compnay: Alamo"
]
}
My program:
#SuppressWarnings("unchecked")
public static void main(String[] args)
{
File text = new File("R:/TestJSON.txt");
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("R:\\Desktop\\TestJSON.txt"));
JSONObject jsonObject = (JSONObject) obj;
List<String> list = new ArrayList<>();
String name = (String) jsonObject.get("Name");
System.out.println(name);
String author = (String) jsonObject.get("Developer");
System.out.println(author);
JSONArray companyList = (JSONArray) jsonObject.get("Project List");
companyList.stream().map(e->{if(e.equals("Compnay: National")); return e;}).collect(Collectors.toList());
list.forEach(System.out::println);
}
catch (Exception e)
{}
}
}
Everything is executing correctly except
companyList.stream().map(e->{if(e.equals("Compnay: National")); return e;}).collect(Collectors.toList());
list.forEach(System.out::println);
I can get the desired result another way around but i want to know why my map is not returning anything?? should it not return Compnay: National.
Result i am getting:
ABC.com
Vishwa ratna
I am expecting:
ABC.com
Vishwa ratna
Compnay: National
Edit: Even after using filter() as suggested by some people here i am unable to get the desired result.

One you have to use filter instead of map.
Second you have to assign the result of collect to list
Your code should be :
list = (List<String>) companyList.stream()
.filter(e-> e.equals("Compnay: National"))
.map(Object::toString)
.collect(Collectors.toList());
Another solution maybe is to after the filter collect toArray, thenyou convert the array to stream use map with Object::toString then collect to list, this can work also
list = Arrays.stream(
companyList.stream()
.filter(e -> e.equals("Compnay: National"))
.toArray())
.map(Object::toString)
.collect(Collectors.toList());
Why filter and not map
map alwayse return a result, so if you make a condition inside map you have to use else part, it works in your case because you have a typo, your condition not make any sinse, but why you use if inside a map, and you have filter where you can avoid conditions?
Stream<T> filter(Predicate<? super T> predicate)
Like you see filter took a predicate and return a new stream not a boolean like you said in your comment

Another solution using Jackson library
I'm not sure what library you are using to parse your Json file, but, it seems not the perfect way, I would suggest another solution using jackson library, so you have :
1- add to pom.xml the dependency :
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
2- create a Job which is similar to your Json file like so :
class MyObject {
private String name;
private String developer;
private List<String> projectList;
public String getName() {
return name;
}
#JsonSetter("Name")
public void setName(String name) {
this.name = name;
}
public String getDeveloper() {
return developer;
}
#JsonSetter("Developer")
public void setDeveloper(String developer) {
this.developer = developer;
}
public List<String> getProjectList() {
return projectList;
}
#JsonSetter("Project List")
public void setProjectList(List<String> projectList) {
this.projectList = projectList;
}
}
3- your code to parse
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
public class Mcve {
public static void main(String[] args) throws IOException {
String path = "R:\\Desktop\\TestJSON.txt";
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
MyObject obj = mapper.readValue(new File(path), MyObject.class);
String name = obj.getName();
System.out.println(name);
String author = obj.getDeveloper();
System.out.println(author);
List<String> list = obj.getProjectList()
.stream()
.filter(e -> e.equals("Compnay: National"))
.collect(Collectors.toList());
list.forEach(System.out::println);
}
}
Outputs
ABC.com
Vishwa ratna
Compnay: National
as you see, working with Objects is more easier and more helpful.

Related

Remove dublicates value from json array in android

[{"product_name":"13X25","ask_size":0,"product_id":"5","category_id":"1","quantity":"10","image":null,"description":"","product_pdf":null,"head":"MARSHAL","price":"22.00","user_quantity":"2"},{"product_name":"14X25","ask_size":0,"product_id":"6","category_id":"1","quantity":"12","image":null,"description":"","product_pdf":null,"head":"MARSHAL","price":"23.00","user_quantity":"1"},{"product_name":"14X25 C","ask_size":0,"product_id":"2","category_id":"1","quantity":"23","image":null,"description":"","product_pdf":null,"head":"KANGARO","price":"22.00","user_quantity":"0"},{"product_name":"17X25 C","ask_size":0,"product_id":"1","category_id":"1","quantity":"18","image":null,"description":"","product_pdf":null,"head":"HOKO","price":"12.00","user_quantity":"0"}]
This is my JSON array
Where I want to remove a particular key if it is already exist
There is a key named "head": "MARSHAL", This Key comes two times but I want to fetch it only one time.
If it's coming then it must be removed automatically from other JSONObject, Not only for one key
it can be to other keys also if they get repeated then I want them only one time and after that add that JSON data to the list
How can I do it for android?
I want to show this data into cardView adapter
First of all, convert your JSON to List<Map<String, Object>>.
You can use ObhectMapper to do so.
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class Test {
private static ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) throws IOException {
List<Map<String, String>> listOfMap = createListMap();
Map<String, List<String>> tempMap = new HashMap<>();
listOfMap.forEach(
map -> {
Set<String> keySet = new HashSet<>(map.keySet());
keySet.forEach(
key -> {
List<String> tempValue = tempMap.get(key);
if (Objects.nonNull(tempValue) && tempValue.contains(map.get(key))) {
map.remove(key);
} else {
tempMap.put(key, Arrays.asList(map.get(key)));
}
});
});
System.out.println(createListMap(listOfMap));
}
private static List<Map<String, String>> createListMap() throws IOException {
File jsonFile = new File("src/main/resources/input.json");
return mapper.readValue(jsonFile, new TypeReference<List<Map<String, String>>>() {});
}
private static String createListMap(List<Map<String, String>> listOfMap) throws IOException {
return mapper.writeValueAsString(listOfMap);
}
}
Below is the output for your input JSON.
[{"product_name":"13X25","ask_size":"0","product_id":"5","category_id":"1","quantity":"10","image":null,"description":"","product_pdf":null,"head":"MARSHAL","price":"22.00","user_quantity":"2"},{"product_name":"14X25","product_id":"6","quantity":"12","price":"23.00","user_quantity":"1"},{"product_name":"14X25
C","product_id":"2","quantity":"23","head":"KANGARO","price":"22.00","user_quantity":"0"},{"product_name":"17X25
C","product_id":"1","quantity":"18","head":"HOKO","price":"12.00"}]
May this serves your purpose.

Gson deserialization skip one quotation

I have to deserialise JSON. I use GSON library for this purpose. I am building a web application. The user fills up where he wants to fly, then the query is sent to the API and the result is returned.
Let us use an example of response:
{"success":true,"data":{"WAW":{"0":{"price":153,"airline":"LO","flight_number":678,"departure_at":"2019-08-05T17:40:00Z","return_at":"2019-08-20T14:35:00Z","expires_at":"2019-05-24T20:55:02Z"},"1":{"price":126,"airline":"A3","flight_number":881,"departure_at":"2019-11-21T11:00:00Z","return_at":"2019-11-26T16:05:00Z","expires_at":"2019-05-27T13:39:23Z"},"2":{"price":171,"airline":"KL","flight_number":900,"departure_at":"2019-09-12T02:40:00Z","return_at":"2019-09-18T17:30:00Z","expires_at":"2019-05-27T10:40:40Z"},"3":{"price":235,"airline":"B2","flight_number":972,"departure_at":"2019-06-12T07:20:00Z","return_at":"2019-06-18T17:30:00Z","expires_at":"2019-05-26T12:31:22Z"},"4":{"price":596,"airline":"TK","flight_number":422,"departure_at":"2019-06-20T00:10:00Z","return_at":"2019-06-24T13:05:00Z","expires_at":"2019-05-26T08:08:21Z"}}},"error":null,"currency":"EUR"}
I created a classes in this way: http://pojo.sodhanalibrary.com
The problem is that there is always the name of the place of arrival. In this case WAW = Warsaw.
gsonConvert.gson(output).getData().getWAW().getFirst().getAirline()
I want to avoid it because the place of arrival will depend on the choice of the user.
You should be able to simplify your data property to type: Map<String, Map<String, Flight>>. Where Flight POJO represents given flight. Model could look like below:
class FlightResponse {
private boolean success;
private Map<String, Map<String, Flight>> data;
private String error;
private String currency;
public Map<String, Flight> getFlatData() {
return data.entrySet()
.stream()
.collect(HashMap::new, (m, e) -> m.putAll(e.getValue()), Map::putAll);
}
// getters, setters, toString
}
class Flight {
private BigDecimal price;
private String airline;
#SerializedName("flight_number")
private int flightNumber;
#SerializedName("departure_at")
private String departureAt;
#SerializedName("return_at")
private String returnAt;
#SerializedName("expires_at")
private String expiresAt;
// getters, setters, toString
}
And example how to parse your JSON:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import java.io.File;
import java.io.FileReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder().create();
FlightResponse flightResponse = gson.fromJson(new FileReader(jsonFile), FlightResponse.class);
flightResponse.getFlatData().forEach((k, v) -> {
System.out.println(k + " => " + v);
});
}
}
Above code prints:
0 => Flight{price=153, airline='LO', flightNumber=678, departureAt='2019-08-05T17:40:00Z', returnAt='2019-08-20T14:35:00Z', expiresAt='2019-05-24T20:55:02Z'}
1 => Flight{price=126, airline='A3', flightNumber=881, departureAt='2019-11-21T11:00:00Z', returnAt='2019-11-26T16:05:00Z', expiresAt='2019-05-27T13:39:23Z'}
2 => Flight{price=171, airline='KL', flightNumber=900, departureAt='2019-09-12T02:40:00Z', returnAt='2019-09-18T17:30:00Z', expiresAt='2019-05-27T10:40:40Z'}
3 => Flight{price=235, airline='B2', flightNumber=972, departureAt='2019-06-12T07:20:00Z', returnAt='2019-06-18T17:30:00Z', expiresAt='2019-05-26T12:31:22Z'}
4 => Flight{price=596, airline='TK', flightNumber=422, departureAt='2019-06-20T00:10:00Z', returnAt='2019-06-24T13:05:00Z', expiresAt='2019-05-26T08:08:21Z'}
See also:
Flatten a Map> to Map with stream and lambda

how to convert a string with square bracket into lots of doubles in Java?

I want to know that how to convert a string from Jsonarray, like the one in the following code, to a list of doubles.
String lineStringJsonArray = "[[[0.093493,51.6037],[0.092077,51.6134],[0.075051,51.6179],[-0.247248,51.5166],[-0.259754,51.5235],[-0.28098,51.518],[-0.301457,51.515]]]"
How should I use pattern to drop those square brackets?
Use json-simple.
Use the JSONArray object that returns an array-of-objects-like object to iterate over. I've compiled an example of printing all the doubles in the arrays, if that's what you wanted.
String lineStringJsonArray = "[[[0.093493,51.6037],[0.092077,51.6134],[0.075051,51.6179],[-0.247248,51.5166],[-0.259754,51.5235],[-0.28098,51.518],[-0.301457,51.515]]]";
JSONParser parser = new JSONParser();
try {
JSONArray arrays3 = (JSONArray) parser.parse(lineStringJsonArray);
JSONArray arrays2 = (JSONArray) arrays3.get(0);
for (Object items : arrays2) {
for (Object item : (JSONArray) items) {
System.out.println((Double) item);
}
}
} catch (ParseException e) {
e.printStackTrace();
}
If you want to decode this JSON string, I would advice you to use Jackson library (http://wiki.fasterxml.com/JacksonHome). You can find help on Google on how to import it and use it.
Then the class to use should look like this :
public class AwesomeClassName extends ArrayList<ArrayList<ArrayList<Double>>> {
}
Please ask if you need any help.
Promoting reuse, I Prefer the answer from #ReutSharabani. However to the original question, to use Pattern, here is another solution:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Play {
static class Pair<T> {
T v1,v2;
Pair(T v1,T v2) { this.v1 = v1; this.v2 = v2; }
#Override public String toString() {
return "(X: "+v1+", Y: "+v2+")";
}
}
public static void main(String args[]) {
List<Pair<Double>> l = new ArrayList<>();
Pattern p = Pattern.compile("\\[([^\\[\\],]*),([^\\[\\],]*)]");
Matcher m = p.matcher("[[[0.093493,51.6037],[0.092077,51.6134],[0.075051,51.6179],[-0.247248,51.5166],[-0.259754,51.5235],[-0.28098,51.518],[-0.301457,51.515]]]");
while (m.find()) {
String v1 = m.group(1);
String v2 = m.group(2);
l.add(new Pair<>(Double.valueOf(v1),Double.valueOf(v2)));
}
l.stream().map(Pair::toString).forEach(System.out::println);
}
}

Gson parsing string that has no key-value pairs

I'm trying to parse a string with Gson library but without success. Here is my string:
[["-1.816513","52.5487566"],["-1.8164913","52.548824"]]
the problem in this example is that there are no key-value pairs. I looked at other examples but all of them had key-value pairs and didn't look like my problem.
My solution to parse a list of list of strings.
package stackoverflow.answers;
import java.lang.reflect.Type;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class GsonTest {
public static void main(String[] arg) {
Gson gson = new Gson();
String jsonOutput = "[[\"-1.816513\",\"52.5487566\"],[\"-1.8164913\",\"52.548824\"]]";
Type listType = new TypeToken<List<List<String>>>() {}.getType();
List<List<String>> strings = (List<List<String>>) gson.fromJson(jsonOutput, listType);
for(List<String> inner: strings){
for(String s: inner){
System.out.println(s);
}
}
}
}
But since values can be "thinked" also a doubles, you can parse them directly changing type into solution:
package stackoverflow.answers;
import java.lang.reflect.Type;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class GsonTest {
public static void main(String[] arg) {
Gson gson = new Gson();
String jsonOutput = "[[\"-1.816513\",\"52.5487566\"],[\"-1.8164913\",\"52.548824\"]]";
Type listType = new TypeToken<List<List<Double>>>() {}.getType();
List<List<Double>> numbers = (List<List<Double>>) gson.fromJson(jsonOutput, listType);
for(List<Double> inner: numbers){
for(Double d: inner){
System.out.println(d);
}
}
}
}
Not important in the context, but for future references: Java 7, Gson 2.2.4
One solution, with raw types:
package com.stackoverflow.so18525283;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.List;
public class App {
private static final String INPUT = "[[\"-1.816513\",\"52.5487566\"],[\"-1.8164913\",\"52.548824\"]]";
public static void main(final String[] args) {
final Gson gson = new GsonBuilder().create();
final List<?> fromJson = gson.fromJson(INPUT, List.class);
if (fromJson != null && fromJson.size() > 0 && fromJson.get(0) instanceof List) {
System.out.println(((List<?>) fromJson.get(0)).get(0)); // this is a String
}
}
}
Another solution is to recreate a valid JSON object, same App as below but with:
public static void main(String[] args) {
final Gson gson = new GsonBuilder().create();
final Foo fromJson = gson.fromJson("{ data: " + INPUT + "}", Foo.class);
// TODO: check for null
System.out.println(fromJson.data.get(0).get(0)); // this is a Double
}
private static class Foo {
List<List<Double>> data;
}

Is there any way to convert a Map to a JSON representation using Jackson without writing to a file?

I'm trying to use Jackson to convert a HashMap to a JSON representation.
However, all the ways I've seen involve writing to a file and then reading it back, which seems really inefficient. I was wondering if there was anyway to do it directly?
Here's an example of an instance where I'd like to do it
public static Party readOneParty(String partyName) {
Party localParty = new Party();
if(connection==null) {
connection = new DBConnection();
} try {
String query = "SELECT * FROM PureServlet WHERE PARTY_NAME=?";
ps = con.prepareStatement(query);
ps.setString(1, partyName);
resultSet = ps.executeQuery();
meta = resultSet.getMetaData();
String columnName, value;
resultSet.next();
for(int j=1;j<=meta.getColumnCount();j++) { // necessary to start at j=1 because of MySQL index starting at 1
columnName = meta.getColumnLabel(j);
value = resultSet.getString(columnName);
localParty.getPartyInfo().put(columnName, value); // this is the hashmap within the party that keeps track of the individual values. The column Name = label, value is the value
}
}
}
public class Party {
HashMap <String,String> partyInfo = new HashMap<String,String>();
public HashMap<String,String> getPartyInfo() throws Exception {
return partyInfo;
}
}
The output would look something like this
"partyInfo": {
"PARTY_NAME": "VSN",
"PARTY_ID": "92716518",
"PARTY_NUMBER": "92716518"
}
So far every example I've come across of using ObjectMapper involves writing to a file and then reading it back.
Is there a Jackson version of Java's HashMap or Map that'll work in a similar way to what I have implemented?
Pass your Map to ObjectMapper.writeValueAsString(Object value)
It's more efficient than using StringWriter, according to the docs:
Method that can be used to serialize any Java value as a String. Functionally equivalent to calling writeValue(Writer,Object) with StringWriter and constructing String, but more efficient.
Example
import org.codehaus.jackson.map.ObjectMapper;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Example {
public static void main(String[] args) throws IOException {
Map<String,String> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
String mapAsJson = new ObjectMapper().writeValueAsString(map);
System.out.println(mapAsJson);
}
}
You can use a StringWriter.
package test;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
public class StringWriterExample {
private static ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) throws IOException {
Map<String,String> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
StringWriter stringWriter = new StringWriter();
objectMapper.writeValue(stringWriter, map);
System.out.println(stringWriter.toString());
}
}
produces
{"key2":"value2","key1":"value1"}

Categories