I have 2 API responses and converted them into Json Array. When I convert 2 jsons into a map of key value pair the order of values are different and unable to perform comparison between 2 API responses.
JsonArray from API 1:
[
{
"employeeSalutation": null,
"EmployeeName": "Example",
"EmployeeCode": "SAA",
"Zip": 12345,
"DepartmentName": "Social science",
"EmployeeAddress": "123 st",
"StateCode": 9,
"updatedDate": "2018-01-22T03:48:43.59",
"EmployeeId": 1257
}
]
Json Array from API 2:
[
{
"Emp_Name": "Example",
"emp_Sal": null,
"Dept_Name": "Social science",
"Emp_addr": "123 st",
"Zip": "12345",
"Stat_cd": 9,
"Emp_id": 1257,
"upd_d": "2018-01-22 03:48:43.59",
"Emp_Code": "SAA"
}
]
I converted 2 Json Arrays into map of key-value pair with EmployeeId as key in Array 1 and Emp_id as key in Array 2. When I compare 2 maps the order of values in map are different and getting failed.
How to compare 2 APIs to ensure the values of each element in 2 apis are matched.
First of all you need to create a model which will represent these two JSON payloads. They are almost similar except of key names and values for Zip key where in first payload it is a number primitive in second - String primitive. Dates also have different format so you need to handle them by implementing custom date deserialiser.
Definitely you should use Jackson or Gson library which allows to deserialise JSON to POJO model, provide custom date deserialisers, any many other features.
Below example provide example solution:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonApi1 = new File("./resource/test.json").getAbsoluteFile();
File jsonApi2 = new File("./resource/test1.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
private final SimpleDateFormat formatWithTimeZoneIndicator = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SS");
private final SimpleDateFormat formatWithoutTimeZoneIndicator = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SS");
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String date = json.getAsString();
try {
return formatWithoutTimeZoneIndicator.parse(date);
} catch (ParseException e) {
try {
return formatWithTimeZoneIndicator.parse(date);
} catch (ParseException e1) {
throw new JsonParseException(e1);
}
}
}
})
.create();
Type employeesType = new TypeToken<List<Employee>>() {}.getType();
try (FileReader readerApi1 = new FileReader(jsonApi1);
FileReader readerApi2 = new FileReader(jsonApi2)) {
List<Employee> employees1 = gson.fromJson(readerApi1, employeesType);
List<Employee> employees2 = gson.fromJson(readerApi2, employeesType);
System.out.println(employees1);
System.out.println(employees2);
System.out.println(employees1.equals(employees2));
}
}
}
class Employee {
#SerializedName(value = "employeeSalutation", alternate = {"emp_Sal"})
private String employeeSalutation;
#SerializedName(value = "EmployeeName", alternate = {"Emp_Name"})
private String employeeName;
#SerializedName(value = "EmployeeCode", alternate = {"Emp_Code"})
private String employeeCode;
#SerializedName("Zip")
private JsonPrimitive zip;
#SerializedName(value = "DepartmentName", alternate = {"Dept_Name"})
private String departmentName;
#SerializedName(value = "EmployeeAddress", alternate = {"Emp_addr"})
private String employeeAddress;
#SerializedName(value = "StateCode", alternate = {"Stat_cd"})
private int stateCode;
#SerializedName(value = "updatedDate", alternate = {"upd_d"})
private Date updatedDate;
#SerializedName(value = "EmployeeId", alternate = {"Emp_id"})
private int employeeId;
public String getEmployeeSalutation() {
return employeeSalutation;
}
public void setEmployeeSalutation(String employeeSalutation) {
this.employeeSalutation = employeeSalutation;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeeCode() {
return employeeCode;
}
public void setEmployeeCode(String employeeCode) {
this.employeeCode = employeeCode;
}
public JsonPrimitive getZip() {
return zip;
}
public void setZip(JsonPrimitive zip) {
this.zip = zip;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getEmployeeAddress() {
return employeeAddress;
}
public void setEmployeeAddress(String employeeAddress) {
this.employeeAddress = employeeAddress;
}
public int getStateCode() {
return stateCode;
}
public void setStateCode(int stateCode) {
this.stateCode = stateCode;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return stateCode == employee.stateCode &&
employeeId == employee.employeeId &&
Objects.equals(employeeSalutation, employee.employeeSalutation) &&
Objects.equals(employeeName, employee.employeeName) &&
Objects.equals(employeeCode, employee.employeeCode) &&
Objects.equals(zip.getAsString(), employee.zip.getAsString()) &&
Objects.equals(departmentName, employee.departmentName) &&
Objects.equals(employeeAddress, employee.employeeAddress) &&
Objects.equals(updatedDate, employee.updatedDate);
}
#Override
public int hashCode() {
return Objects.hash(employeeSalutation, employeeName, employeeCode, zip, departmentName, employeeAddress, stateCode, updatedDate, employeeId);
}
#Override
public String toString() {
return "Employee{" +
"employeeSalutation='" + employeeSalutation + '\'' +
", employeeName='" + employeeName + '\'' +
", employeeCode='" + employeeCode + '\'' +
", zip=" + zip +
", departmentName='" + departmentName + '\'' +
", employeeAddress='" + employeeAddress + '\'' +
", stateCode=" + stateCode +
", updatedDate='" + updatedDate + '\'' +
", employeeId=" + employeeId +
'}';
}
}
Above code prints:
[Employee{employeeSalutation='null', employeeName='Example', employeeCode='SAA', zip=12345, departmentName='Social science', employeeAddress='123 st', stateCode=9, updatedDate='Mon Jan 22 03:48:43 CET 2018', employeeId=1257}]
[Employee{employeeSalutation='null', employeeName='Example', employeeCode='SAA', zip="12345", departmentName='Social science', employeeAddress='123 st', stateCode=9, updatedDate='Mon Jan 22 03:48:43 CET 2018', employeeId=1257}]
true
JSONAssert librairy is very handy for such tasks.
Here is good tutorial on how to use it.
I hope it helps you.
Since you are doing this in Java, I suggest you map this values into Java objects.
That way, it would be extremely easy for you to compare values. You can use libraries like Gson for that but here i will show you how to do that without a library.
Create a class which will be easy to use for your API responses:
public class Employee {
private String employeeSalutation; //i am not sure what type should this variable be
private String employeeName;
private String employeeCode;
private int zip;
private String departmentName;
private String employeeAddress;
private int stateCode;
private String updatedDate;
private int employeeId;
//this is where your parser can be used
public Employee(String employeeSalutation, String employeeName, String employeeCode,
int zip, String departmentName, String employeeAddress, int stateCode,String updatedDate, int employeeId){
this.employeeSalutation = employeeSalutation;
this.employeeName = employeeName;
this.employeeCode = employeeCode;
this.zip = zip;
this.departmentName = departmentName;
this.employeeAddress = employeeAddress;
this.stateCode = stateCode;
this.updatedDate = updatedDate;
this.employeeId = employeeId;
}
//getters, setters
}
Now you could have a class which will be used to convert this arrays into Java Objects, lets call it EmployeeConverter:
public class EmployeeConverter {
public Employee convertApi1Employee(String json){
//since you didn't clarify how are you accessing your Json values, i will now use pseudo-code to finish my answer.
//using variable.value pseudo-code to access json property value
return new Employee(employeeSalutation.value, EmployeeName.value, EmployeeCode.value, Zip.value, DepartmentName.value, EmployeeAddress.value, EmployeeAddress.value, StateCode.value, updatedDate.value, EmployeeId.value);
}
}
You should create method convertApi2Employee() which will have exact functionality as convertApi1Employee() method, but will use different JSON object.
I hope this helps.
Related
so i have a database that has a payment entity within it, the payment entity has few parameters, the most important one is the date parameter, the problem that am facing is am trying to sort the list of payments in the database into a list of lists, each mini list contains the payments made on the same day, here is an image so you can better understand what am trying to explain.
i don't know how do i go about this whatsoever so am just looking for some guidance on how i should approach this.
i don't think that any code is needed here but here is the code to the payment class, and am more than happy to provide more code if it's needed :
public class Payment {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "id_payment")
int paymentID;
#Embedded
SubjectTeacherCrossRef subjectTeacherCrossRef;
#ColumnInfo(name = "payment_date")
String paymentDate;
#ColumnInfo(name = "payment_total")
int paymentTotal;
public void setPaymentID(int paymentID) {
this.paymentID = paymentID;
}
public Payment(SubjectTeacherCrossRef subjectTeacherCrossRef, String paymentDate, int paymentTotal) {
this.subjectTeacherCrossRef = subjectTeacherCrossRef;
this.paymentDate = paymentDate;
this.paymentTotal = paymentTotal;
}
public int getPaymentID() {
return paymentID;
}
public SubjectTeacherCrossRef getSubjectTeacherCrossRef() {
return subjectTeacherCrossRef;
}
public String getPaymentDate() {
return paymentDate;
}
public int getPaymentTotal() {
return paymentTotal;
}
}
You should iterate on all Payment fetched from DB.
Get the paymentDate from each Payment and store it in a Map<Date, List<Payment>>.
You must first check in the map if a value (List<Payment>) already exists for given key (the date). If not, you must first create the List<Payment> instance and put it in the map put(the_date, the_list).
Se method addPayment(Payment payment) below.
Remark: you should use a java.util.Date object to represent a date rather than a String
package stackoverflow;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PaymentMap {
private Map<String, List<Payment>> map;
public PaymentMap() {
super();
map = new HashMap<String, List<Payment>>();
System.out.println("map created");
}
public void addPayment(Payment payment) {
List<Payment> payments;
String paymentDate = payment.getPaymentDate();
if ((payments = map.get(paymentDate)) == null) {
payments = new ArrayList<Payment>();
map.put(paymentDate, payments);
}
payments.add(payment);
System.out.println("Payment " + payment + " added");
}
public void printMapContent() {
System.out.println("Map content : " +
Arrays.toString(map.entrySet().toArray()));
}
class Payment {
private int paymentID;
private SubjectTeacherCrossRef subjectTeacherCrossRef;
private String paymentDate;
private int paymentTotal;
public Payment(SubjectTeacherCrossRef subjectTeacherCrossRef, String paymentDate, int paymentTotal) {
this.subjectTeacherCrossRef = subjectTeacherCrossRef;
this.paymentDate = paymentDate;
this.paymentTotal = paymentTotal;
}
public int getPaymentID() {
return paymentID;
}
public SubjectTeacherCrossRef getSubjectTeacherCrossRef() {
return subjectTeacherCrossRef;
}
public String getPaymentDate() {
return paymentDate;
}
public int getPaymentTotal() {
return paymentTotal;
}
#Override
public String toString() {
return new StringBuilder("Payment :: date: "+paymentDate+ " - total : "+paymentTotal).toString();
}
}
public static void main(String[] args) {
PaymentMap map = new PaymentMap();
// Adding 3 payments on date 1
String date1 = "20220128";
map.addPayment(map.new Payment(null, date1, 1234));
map.addPayment(map.new Payment(null, date1, 2345));
map.addPayment(map.new Payment(null, date1, 3456));
// Adding 2 payments on date 2
String date2 = "20221125";
map.addPayment(map.new Payment(null, date2, 4567));
map.addPayment(map.new Payment(null, date2, 5678));
// Adding 2 payments on date 3
String date3 = "20221202";
map.addPayment(map.new Payment(null, date3, 6789));
map.addPayment(map.new Payment(null, date3, 7890));
// Printing map content
map.printMapContent();
}
}
I have an Android App (written in Java) which retrieves a JSON object from the backend, parses it, and displays the data in the app. Everything is working fine (meaning that every field is being displayed correctly) except for one field. All the fields being displayed correctly are String whereas the one field which is causing the error is a string array!
Sample Object being retried from backend:
{
"attendance_type": "2",
"guest": [
"Test Guest",
"Test Guest 2"
],
"member_id": "1770428",
"attendance_time": "2020-04-27 04:42:22",
"name": "HENRY HHH",
"last_name": "",
"email": "henry#mailinator.com",
"onesignal_playerid": "",
"user_image": "311591.png",
"dateOfBirth": "06/22/1997",
"employeeID": "543210",
"socialSecurityNumber": "0000"
}
As I said, all the fields are being retrieved correctly except the "guest field"
This is the class in which everything is Serialized:
package com.lu.scanner.ui.attendance.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class AttendanceDetails {
String date;
#SerializedName("attendance_type")
private String attendance_type;
#SerializedName("member_id")
private String member_id;
#SerializedName("attendance_date")
private String attendance_date;
#SerializedName("name")
private String name;
#SerializedName("email")
private String email;
#SerializedName("onesignal_playerid")
private String onesignal_playerid;
#SerializedName("user_image")
private String user_image;
#SerializedName("dateOfBirth")
private String dateOfBirth;
#SerializedName("employeeID")
private String employeeID;
#SerializedName("socialSecurityNumber")
private String socialSecurityNumber;
#SerializedName("attendance_time")
private String attendance_time;
#SerializedName("guest")
private String[] guest;
public AttendanceDetails(String date) {
this.date = date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getAttendance_type() {
return attendance_type;
}
public void setAttendance_type(String attendance_type) {
this.attendance_type = attendance_type;
}
public String getMember_id() {
return member_id;
}
public void setMember_id(String member_id) {
this.member_id = member_id;
}
public String getAttendance_date() {
return attendance_date;
}
public void setAttendance_date(String attendance_date) {
this.attendance_date = attendance_date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getOnesignal_playerid() {
return onesignal_playerid;
}
public void setOnesignal_playerid(String onesignal_playerid) {
this.onesignal_playerid = onesignal_playerid;
}
public String getUser_image() {
return user_image;
}
public void setUser_image(String user_image) {
this.user_image = user_image;
}
public String getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(String dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getEmployeeID() {
return employeeID;
}
public void setEmployeeID(String employeeID) {
this.employeeID = employeeID;
}
public String getSocialSecurityNumber() {
return socialSecurityNumber;
}
public void setSocialSecurityNumber(String socialSecurityNumber) {
this.socialSecurityNumber = socialSecurityNumber;
}
public String getAttendance_time() {
return attendance_time;
}
public void setAttendance_time(String attendance_time) {
this.attendance_time = attendance_time;
}
public String[] getGuest(){
return guest;
}
public void setGuest(String[] guest){
this.guest=guest;
}
}
This is the SQLLite database:
private static final String CREATE_TABLE_ATTENDANCE_DETAILS = "CREATE TABLE IF NOT EXISTS " + TABLE_ATTENDANCE_DETAILS +
"( date TEXT , " +
"attendance_type TEXT, " +
"member_id TEXT, " +
"attendance_date TEXT, " +
"name TEXT, " +
"email TEXT, " +
"onesignal_playerid TEXT, " +
"user_image TEXT, " +
"dateOfBirth TEXT, " +
"employeeID TEXT, " +
"socialSecurityNumber TEXT, " +
"attendance_time TEXT, " +
"guest TEXT); ";
And finally, there is where the data is being retrieved:
public List<AttendanceDetails> getAllAttendanceDetails() {
List<AttendanceDetails> attendanceDetailsList = new ArrayList<AttendanceDetails>();
String selectQuery = "SELECT * FROM " + TABLE_ATTENDANCE_DETAILS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
AttendanceDetails attendanceDetails = new AttendanceDetails();
attendanceDetails.setDate(cursor.getString(0));
attendanceDetails.setAttendance_type(cursor.getString(1));
attendanceDetails.setMember_id(cursor.getString(2));
attendanceDetails.setAttendance_date(cursor.getString(3));
attendanceDetails.setName(cursor.getString(4));
attendanceDetails.setEmail(cursor.getString(5));
attendanceDetails.setOnesignal_playerid(cursor.getString(6));
attendanceDetails.setUser_image(cursor.getString(7));
attendanceDetails.setDateOfBirth(cursor.getString(8));
attendanceDetails.setEmployeeID(cursor.getString(9));
attendanceDetails.setSocialSecurityNumber(cursor.getString(10));
attendanceDetails.setAttendance_time(cursor.getString(11));
attendanceDetails.setGuest(cursor.getString(12));
attendanceDetailsList.add(attendanceDetails);
} while (cursor.moveToNext());
}
return attendanceDetailsList;
}
Therefore, the main problem, I think, is that the TEXT type in the table creation is not compatible with the String array. Plus I think the cursor.String() function is not working for the "guest" string array properly. What can I do to make all of this code compatible with the "guest" field?
NOTE: Everything is working perfectly fine except for the guest field...
A Database stores rows of data, divided into columns. Each column is a skalar. SQLite only supports (basically) numbers and Text for columns. A List of Texts (or array from strings) doesn't fit in there. You are trying to assign a single String to an array.
You have two options:
Model guest as its own table and use foreign keys and the appropriate JOIN to fetch the data.
Encode the data yourself. If you don't want to query the array, but always retrieve the whole thing, this is the easier way:
Gson gson;
String guestSerialized = gson.toJson(attendanceDetails.getGuest);
// Insert data like this
// Retrieve:
attendanceDetails.setGuest(gson.fromJson(cursor.getString(12), String[].class))
That is, if you are using GSON for JSON (de)serialization. You can choose a different format or library.
Maybe you could give some name in the fields of "guest", something like:
"guest": [
{
"guest" : "Test Guest",
},
{
"guest" : "Test Guest 2"
},
],
Then, in order to read these values, you can do that:
JSONArray ja = (JSONArray) jo.get("guest");
Map address = ((Map)jo.get("guest"))
Iterator itr = ja.iterator();
Iterator<Map.Entry> itr1;
while (itr.hasNext()) {
itr1 = ((Map) itr.next()).entrySet().iterator();
while (itr1.hasNext()) {
Map.Entry pair = itr1.next();
System.out.println(pair.getKey() + " : " + pair.getValue());
}
}
Where:
pair.getKey is the name of the key ("guest")
pair.getValue is the value of the key ("Test Guest")
The source code is here.
Sorry if I have made any mistakes. Please ask for clarifications! :)
I have a JSON as below. The goal is to get the corresponding "ip","PRODUCTTYPE" and "ID" values.
{
"customerId": "dummy1",
"nameIdmap": {
"10.2.1.0": "{PRODUCTTYPE=null, ID=123}",
"10.2.1.3": "{PRODUCTTYPE=null, ID=456}",
"10.2.1.4": "{PRODUCTTYPE=null, ID=789}",
"10.2.1.5": "{PRODUCTTYPE=null, ID=193}"
}
}
I am using the ObjectMapper API to parse and fetch the values.
ObjectMapper om = new ObjectMapper();
JsonNode node = om.readTree(stringToBeParsed);
String customerID = node.get("customerId").asText();
System.out.println("The Customer ID is ::: "+customerID);
JsonNode nameIdmap = node.get("nameIdmap");
StreamSupport.stream(nameIdmap.spliterator(), false).forEach(
kv -> {
System.out.println(kv.asText().split(",")[0] +" ,
"+kv.asText().split(",")[1]);
});
But the issue is I, am unable to get the key which is the ip-address in this case. Tried different ways to achieve but could not get what i want.
I checked if the nameIdmap is an array nameIdmap.isArray() but it is false.
I also tried below but could not get the ip i.e the key
JsonNode nameIdmap = node.get("nameIdmap");
StreamSupport.stream(nameIdmap.spliterator(), false).collect(Collectors.toList())
.forEach(item -> {
System.out.println(item.asText());
});;
You can try Custom Deserializer as below
1. Create Item class
This is a POJO which stands for an ID and a map of String and IPItem
public class SOItem {
#Override
public String toString() {
return "SOItem [id=" + id + ", map=" + map + "]";
}
String id;
Map<String, SOIPItem> map = new HashMap();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, SOIPItem> getMap() {
return map;
}
public void setMap(Map<String, SOIPItem> map) {
this.map = map;
}
}
2. Create IPItem class
This is a POJO for an ID and ProductType
public class SOIPItem {
private String type;
private String id;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public String toString() {
return "SOIPItem [type=" + type + ", id=" + id + "]";
}
public SOIPItem(String type, String id) {
super();
this.type = type;
this.id = id;
}
}
3. Create a Custom Deserializer
import java.io.IOException;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
public class SOCustDeser extends StdDeserializer<SOItem> {
public SOCustDeser() {
this(null);
}
public SOCustDeser(Class<?> vc) {
super(vc);
}
/**
*
*/
private static final long serialVersionUID = -394222274225082713L;
#Override
public SOItem deserialize(JsonParser parser, DeserializationContext arg1)
throws IOException, JsonProcessingException {
SOItem soItem = new SOItem();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
soItem.setId(node.get("customerId").asText());
JsonNode idmap = node.get("nameIdmap");
Iterator<String> fieldNames = idmap.fieldNames();
while(fieldNames.hasNext()) {
String ip = fieldNames.next();
String textValue = idmap.get(ip).asText();
Pattern p = Pattern.compile("(.*?)=(.*?),(.*?)(\\d+)");
Matcher m = p.matcher(textValue);
if (m.find()) {
soItem.map.put(ip, new SOIPItem(m.group(2), m.group(4)));
}
}
return soItem;
}
}
4. Test class
import java.io.File;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class MicsTest {
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper();
SimpleModule sm = new SimpleModule();
sm.addDeserializer(SOItem.class, new SOCustDeser());
om.registerModule(sm);
SOItem item = om.readValue(new File("c:\\temp\\test.json"), SOItem.class);
System.out.println(item);
}
}
5. Output
SOItem [id=dummy1, map={10.2.1.0=SOIPItem [type=null, id=123], 10.2.1.3=SOIPItem [type=null, id=456], 10.2.1.5=SOIPItem [type=null, id=193], 10.2.1.4=SOIPItem [type=null, id=789]}]
You can get the field names by nameIdmap.getFieldNames as an iterator. You can then iterate over like that:
...
Iterator<String> fieldNames = idmap.getFieldNames();
while(fieldNames.hasNext()) {
String ip = fieldNames.next();
String textValue = idmap.get(ip).getTextValue()
System.out.println(ip + ":" + textValue);
}
If the nested information is also JSON you can then access it further via idmap.get(ip).get("ID"); if not then you still have the option to find it by regex like that:
Pattern p = Pattern.compile("ID=(\\d+)");
Matcher m = p.matcher(textValue);
if(m.find()) {
System.out.println(ip + ":" + m.group(1));
}
Best way to handle these scenarios is to create a matching pojo for your json. This way it gives you flexibility to play around with the data.
Create classes like these
public class Someclass {
private String customerId;
Map<String, String> nameIdmap;
public Map<String, String> getNameIdmap() {
return nameIdmap;
}
public void setNameIdmap(Map<String, String> nameIdmap) {
this.nameIdmap = nameIdmap;
}
public Someclass() {
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
}
And this code will translate your json to SomeClass class
String json = "<copy paste your json here>";
Someclass someclass = objectMapper.readValue(json, Someclass.class);
String s = someclass.getNameIdmap().get("10.2.1.0");
String[] splits = s.split(" ");
String productType = splits[0].split("=")[1];
String id = splits[1].split("=")[1];
System.out.println(productType + " " + id);
I am getting an exception while trying to filter and iterate over a Optional using Java 8. I have an object Subject which is being added in an array list and a value of null also.
Problem Statement: I have an ArrayList, I want to iterate it, filter it and then based on that, only print that record which fulfills the condition.
package com.example.app;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class OptionalTest {
public static void main(String[] args) {
System.out.println("getSubject: " + getSubjects());
// print the Subject with the name "Math"
System.out.println("getSubject " + getSubjects().filter((Subject s) -> s.getName().equalsIgnoreCase("Math")));
}
private static Optional getSubjects() {
Subject subject1 = new Subject(1, "Math", (short)2, "");
Subject subject2 = new Subject(2, "Social Science", (short)4, "Social Science");
Subject subject3 = new Subject(3, "English", (short)6, "Literature");
List<Subject> subjects = new ArrayList<>();
Optional<List<Subject>> optional = Optional.of(subjects);
subjects.add(subject1);
subjects.add(subject2);
subjects.add(null);
subjects.add(subject3);
return optional;
}
}
class Subject {
int id;
String name;
short type;
String description;
public Subject(int id, String name, short type, String description) {
this.id = id;
this.name = name;
this.type = type;
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public short getType() {
return type;
}
public void setType(short type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return "\nSubject{" + "id=" + id + ", name=" + name + ", type=" + type + ", description=" + description + '}'+"\n";
}
}
Using Optional.filter would be used to filter List instances as per your code snippet. This is not what you want:
Optional.of(getSubjects()).filter(predicate) //filters lists, not subjects in lists
Your intention is probably to use the a list of Subject objects, then filter. It's the filter method of the Stream interface that returns an Optional instance:
I'd change this method:
private static List<Subject> getSubjects(){
Subject subject1 = new Subject(1, "Math", (short)2, "");
Subject subject2 = new Subject(2, "Social Science", (short)4, "Social Science");
Subject subject3 = new Subject(3, "English", (short)6, "Literature");
List<Subject> subjects = new ArrayList<>();
subjects.add(subject1);
subjects.add(subject2);
subjects.add(null);
subjects.add(subject3);
return subjects;
}
And then use it as follows:
Optional<Subject> filtered = getSubjects()
.stream().filter(s -> s.getName().equalsIgnoreCase("Math"))
//Find first is just one of the many Stream methods
//returning an optional
//It's correct to use it in this case because you know
//only one value is expected to match the filter predicate.
.findFirst();
In fact, if you expect more than one subject to match your filter, you should collect, instead, instead of picking one. In this case, you don't need an optional:
List<Subject> mathSubjects = getSubjects()
.stream().filter((s -> s.getName().equalsIgnoreCase("Math")))
.collect(Collectors.toList());
You can do it very simply using lambda expression, I am providing you a sample so that you can modify according to your need.
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class Java8Optional {
public static void main(String[] args) {
List<Employee> employeeList = new ArrayList<>();
employeeList.add(new Employee(1, "syed"));
employeeList.add(new Employee(2, "az"));
employeeList.add(null);
employeeList.add(new Employee(4, "Rof"));
employeeList.forEach(n -> Optional.ofNullable(n).ifPresent(e -> System.out.println("Employee ID="+e.employeeId+"\tEmployee Name="+e.employeeName)));
}
static class Employee {
Integer employeeId;
String employeeName;
public Integer getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public Employee(Integer employeeId, String employeeName) {
super();
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
}
There is a database (northwind) on my machine and I have to write a code in java so as to extract the data from the table (Customers) stored in the database.
If this was only specific to Customers table then I would have done it but I want to make my code generic so that I can extract data from other tables also by simply giving the name of the table in a string variable.
Please have a look to my code.
Main class
package main;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import model.TableModel;
import service.DBConnection;
import service.WriteExcel;
public class Main {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
double start = System.nanoTime();
String tableName = "Customers";
Class<?> c = Class.forName(tableName);
Connection conn = new DBConnection().getConnection();
System.out.println("Connection Established");
QueryRunner run = new QueryRunner();
ResultSetHandler<List<TableModel>> resultHandler = new BeanListHandler<TableModel>(c.getClass())
List<TableModel> data = run.query(conn, "SELECT * FROM `" + tableName + "`;",
resultHandler);
WriteExcel we = new WriteExcel(tableName+"_sheet", new File(tableName+".xlsx"));
we.writeMultipleRows(data);
we.writeWorkbookToFile();
System.out.println("File Written Succesfully");
conn.close();
System.out.println("Time Taken: " + (System.nanoTime()-start)/1000000+" ms");
}
}
In the above code, at line 27, If the statement would have been as follows
ResultSetHandler<List<TableModel>> resultHandler = new BeanListHandler<TableModel>(Customers.class);
This is running perfectly, as I said I want this statement to be independent of the table name, making my code more general.
TableModel
package model;
import java.util.List;
public interface TableModel {
public List<String> getObjectAsList();
}
Customers
package model;
import java.util.ArrayList;
import java.util.List;
public class Customers implements TableModel {
private String customerId;
private String companyName;
private String contactName;
private String contactTitle;
private String address;
private String city;
private String region;
private String postalCode;
private String country;
private String phone;
private String fax;
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getContactTitle() {
return contactTitle;
}
public void setContactTitle(String contactTitle) {
this.contactTitle = contactTitle;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public List<String> getObjectAsList(){
List<String> fields = new ArrayList<>();
fields.add(customerId);
fields.add(companyName);
fields.add(contactName);
fields.add(contactTitle);
fields.add(address);
fields.add(city);
fields.add(region);
fields.add(postalCode);
fields.add(country);
fields.add(phone);
fields.add(fax);
return fields;
}
#Override
public String toString() {
return "{ CustomerID = "+getCustomerId()+","
+ " CompanyName = "+getCompanyName()+","
+ " ContactName = "+getContactName()+","
+ " ContactTitle = "+getContactTitle()+","
+ " Address = "+getAddress()+","
+ " City = "+getCity()+","
+ " Region = "+getRegion()+","
+ " PostalCode = "+getPostalCode()+","
+ " Country = "+getCountry()+","
+ " Phone = "+getPhone()+","
+ " Fax = "+getFax()+"}";
}
}
I have used DbUtils library for extracting database.
Any further suggestion for enhancing my code is welcomed.
If I understand your question right, you could try something like below.
To query the table, you can use run.query(SQL, ResultHandler).
ResultSetHandler<List<Map<String, Object>>> resultHandler = genericResultHandler();
List<Map<String, Object>> result = null;
// Execute the SQL statement and return the results in a List of
// T objects generated by the BeanListHandler.
try
{
result = run.query(sqlQuery, resultHandler, varargs);
}
catch (SQLException e)
{
e.printStackTrace();
}
result.stream().forEach(System.out::println);
The interesting part here is the private method genericResultHandler. For demonstration purposes, I used a HashMap to store the values and the corresponding cloumn names.
private ResultSetHandler<List<Map<String, Object>>> genericResultHandler()
{
return new ResultSetHandler<List<Map<String, Object>>>()
{
#Override
public List<Map<String, Object>> handle(java.sql.ResultSet rs) throws SQLException
{
List<Map<String, Object>> result = new ArrayList<>();
// Query all rows of the table.
while (rs.next())
{
// Get metadata of the table.
java.sql.ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
Map<String, Object> data = new HashMap<>();
// For each column store column name and value of the cell into the hashmap.
for (int i = 1; i < cols; i++)
{
String colName = meta.getColumnName(i);
Object value = rs.getObject(colName);
data.put(colName, value);
}
// Add the row to the result list.
result.add(data);
}
return result;
}
};
}
Afterwards some imports I have used:
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
Output would be something like this (for my test table):
{month=JANUARY, temperature=1.6, globalradiation=0.0, monthid=1}
{month=FEBRUARY, temperature=-0.9, globalradiation=0.0, monthid=2}
{month=MARCH, temperature=0.9, globalradiation=0.0, monthid=3}
{month=APRIL, temperature=7.2, globalradiation=0.0, monthid=4}
{month=MAY, temperature=14.1, globalradiation=0.0, monthid=5}