Unable to sort date in java using android studio - java

I want to sort my array based on their latest dates. I am retrieving the date as a string from a text file. My text file is a follows:
title:High Five
date:02-04-2019
title:Roly Poly
date:04-07-2019
title:Barney
date:11-01-2016
I want to display them as follows:
title:Roly Poly
date:04-07-2019
title:High Five
date:02-04-2019
title:Barney
date:11-01-2016
I have use the following method:
public class mydateCompare implements Comparator<Cartoon>
{
#Override
public int compare(Cartoon o1, Cartoon o2) {
SimpleDateFormat dateFormat=new SimpleDateFormat("dd-mm-yyyy");
String dateinString = o1.getDate();
String dateinS = o2.getDate();
try {
Date date = dateFormat.parse(dateinString);
Date dt = dateFormat.parse(dateinS);
} catch (ParseException e) {
e.printStackTrace();
}
return dateinString.compareTo(dateinS);
}
}
My output from the above method is:
title:High Five
date:02-04-2019
title:Roly Poly
date:04-07-2019
title:Barney
date:11-01-2016
Can you guys tell me what I need to do the get my desired output? Thank you.

Currently, you are comparing the strings which sorts the entries incorrectly. I suggest that you parse the strings to LocalDate from the Java 8 Date/Time API with a custom formatter. The (unchecked) exception should be handled outside the comparator since you cannot compare the entries without the parsed date.
As a side-note, it would be better to already use parsed dates in your Cartoon object.
Here is an example for the comparator:
public class CartoonDescendingDateComparator implements Comparator<Cartoon> {
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd-MM-yyyy");
#Override
public int compare(Cartoon o1, Cartoon o2) {
LocalDate d1 = LocalDate.parse(o1.getDate(), DATE_FORMATTER);
LocalDate d2 = LocalDate.parse(o2.getDate(), DATE_FORMATTER);
return d2.compareTo(d1); // descending order
}
}
Here is a test case with your data:
List<Cartoon> cartoons = new ArrayList<>();
cartoons.add(new Cartoon("High Five", "02-04-2019"));
cartoons.add(new Cartoon("Roly Poly", "04-07-2019"));
cartoons.add(new Cartoon("Barney", "11-01-2016"));
cartoons.sort(new CartoonDescendingDateComparator());
cartoons.forEach(c -> System.out.println("title:" + c.getTitle() + "\ndate:" + c.getDate()));
Output:
title:Barney
date:11-01-2016
title:High Five
date:02-04-2019
title:Roly Poly
date:04-07-2019

Copy the class below,
internal class CartoonsSorter : Comparator<Cartoon> {
private val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault())
override fun compare(o1: Cartoon, o2: Cartoon): Int {
var firstObjDate = Date()
var secondObjDate = Date()
try {
firstObjDate = dateFormat.parse(o1.date) ?: Date()
secondObjDate = dateFormat.parse(o2.date) ?: Date()
} catch (e: ParseException) {
e.printStackTrace()
}
return secondObjDate.compareTo(firstObjDate)
}
}
Use it in the below way,
Collections.sort(yourArray, CartoonsSorter())
Output for the above:
Before Sorting:
[
{
"date": "02-04-2019",
"title": "High Five"
},
{
"date": "04-07-2019",
"title": "Roly Poly"
},
{
"date": "11-01-2016",
"title": "Barney"
}
]
After Sorting:
[
{
"date": "04-07-2019",
"title": "Roly Poly"
},
{
"date": "02-04-2019",
"title": "High Five"
},
{
"date": "11-01-2016",
"title": "Barney"
}
]

Related

Compare if one JSON payload contains another JSON payload

I have 3 JSON payloads: A, B and C. I need to find out if payload A contains B and C.
When B is compared against A, I need the result to be true.
When C is compared against A, I need the result to be false
as college key does not exist in payload A.
Note: Below JSON payloads are just examples and can have different structure and values.
Payload A:
{
"id": "1",
"search": {
"name": "Testing",
"age": "25",
"school": "sacred heart"
},
"Address": {
"street": "Abcedf",
"road": "4th cross",
"city": "bangalore"
}
}
Payload B
{
"id": "1",
"search": {
"name": "Testing"
},
"Address": {
"street": "Abcedf",
"road": "4th cross"
}
}
Payload C
{
"id": "1",
"search": {
"name": "Testing",
"college": "global"
},
"Address": {
"street": "Abcedf",
"road": "4th cross"
}
}
First step would be to create Java objects from your Json. You can use Gson, Jackson or any other library of your choice. For this example I have used Gson.
Your class definition
private class JsonObject {
String id;
Map search;
#SerializedName(value="Address")
Map address;
// getter and setter
}
Parsing objects ( a,b and c are your Json Strings )
Gson gson = new Gson();
JsonObject objectA = gson.fromJson( a, JsonObject.class);
JsonObject objectB = gson.fromJson( b, JsonObject.class);
JsonObject objectC = gson.fromJson( c, JsonObject.class);
For the actual comparison there are many ways to accomplish what you need. One way would be to implement your own method for comparing the objects
private static boolean check( JsonObject firstObject, JsonObject secondObject ) {
return firstObject.getAddress().entrySet().containsAll( secondObject.getAddress().entrySet() )
&& firstObject.getSearch().entrySet().containsAll( secondObject.getSearch().entrySet() );
}
Call the method
System.out.println( check ( objectA, objectB ) );
System.out.println( check ( objectA, objectC ) );
Result
true
false
Your can, of course create your own logic to compare your Maps inside the objects. Take a look at Java Collections Framework or the Guava library which offers some handy utility methods for working with Collections.
You can utilise JsonPointer to implement contains method. A.contains(B) method returns true when object A contains all pointers which has object B and all values are the same. Two objects (A and B) are equal when A.contains(B) and B.contains(A). From definition: A.contains(A) returns true for every A.
Simple implementation could look like below:
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class JsonPointersApp {
public static void main(String[] args) throws IOException {
File aJsonFile = new File("./resource/a.json").getAbsoluteFile();
File bJsonFile = new File("./resource/b.json").getAbsoluteFile();
File cJsonFile = new File("./resource/c.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
JsonPayload payloadA = new JsonPayload(mapper.readTree(aJsonFile));
JsonPayload payloadB = new JsonPayload(mapper.readTree(bJsonFile));
JsonPayload payloadC = new JsonPayload(mapper.readTree(cJsonFile));
System.out.println("JSON A:" + payloadA);
System.out.println("JSON B:" + payloadB);
System.out.println("JSON C:" + payloadC);
System.out.println("A contains B:" + payloadA.contains(payloadB));
System.out.println("A contains C:" + payloadA.contains(payloadC));
System.out.println("B contains C:" + payloadB.contains(payloadC));
System.out.println("C contains B:" + payloadC.contains(payloadB));
System.out.println("A contains A:" + payloadA.contains(payloadA));
}
}
class JsonPayload {
private final JsonNode root;
private final List<JsonPointer> pointers = new ArrayList<>();
JsonPayload(JsonNode root) {
this.root = Objects.requireNonNull(root);
findPointers(this.root, "");
}
public boolean contains(JsonPayload other) {
//If number of pointers are different, JSON payloads are also different
if (this.pointers.size() < other.pointers.size()) {
return false;
}
// If pointers are not the same
if (!this.pointers.containsAll(other.pointers)) {
return false;
}
// check values
return other.pointers
.stream()
.allMatch(p -> this.root.at(p).equals(other.root.at(p)));
}
private void findPointers(JsonNode node, String path) {
if (node.isObject()) {
node.fields().forEachRemaining(entry -> findPointers(entry.getValue(), path + "/" + entry.getKey()));
} else if (node.isArray()) {
final int size = node.size();
for (int i = 0; i < size; i++) {
findPointers(node.get(i), path + "/" + i);
}
} else {
pointers.add(JsonPointer.compile(path));
}
}
#Override
public String toString() {
return pointers.toString();
}
}
Above code prints:
JSON A:[/id, /search/name, /search/age, /search/school, /Address/street, /Address/road, /Address/city]
JSON B:[/id, /search/name, /Address/street, /Address/road]
JSON C:[/id, /search/name, /search/college, /Address/street, /Address/road]
A contains B:true
A contains C:false
B contains C:false
C contains B:true
A contains A:true

iterate over .json file and print all values in JAVA [duplicate]

This question already has answers here:
How to iterate over a JSONObject?
(15 answers)
Closed 2 years ago.
this is a prices.json file which contains many products prices
i need iterate over this .json in order to compare with another json output from another system
i need to get only the fields
"MATNR" field which contains the product ID
and
"NET_PRICE" = contain the price before VAT
and
"PRICE_INC_TAX" = contain the price after VAT
[
{
"customer": {
"AUART": "",
"KALSM": "ZDPS00",
"KUNNR": "0001234567",
"SPRAS": "",
"VKGRP": "",
"VKORG": "1000",
"VTWEG": "10",
"ZMDD": "99",
"ZTERM": ""
},
"outdated": false,
"outputs": [
{
"KUNNR": "0001234567",
"KWMENG": "1",
"MATNR": "000000000001000001",
"NET_PRICE": "15.50",
"NET_PRICE_PER_BASE_UNIT": "15.50",
"ORDER": "1",
"PRICE_INC_TAX": "18.13",
"PRICE_INC_TAX_PER_BASE_UNIT": "18.13",
"TOTAL_TIME": "Total Calculation Time: 15ms",
"VRKME": "EA",
"converted_quantity": "1.00"
},
{
"KUNNR": "0001234567",
"KWMENG": "1",
"MATNR": "000000000001000002",
"NET_PRICE": "20.00",
"NET_PRICE_PER_BASE_UNIT": "20.00",
"ORDER": "1",
"PRICE_INC_TAX": "23.40",
"PRICE_INC_TAX_PER_BASE_UNIT": "23.40",
"TOTAL_TIME": "Total Calculation Time: 12ms",
"VRKME": "EA",
"converted_quantity": "1.00"
},
{
"KUNNR": "0001234567",
"KWMENG": "1",
"MATNR": "000000000001000003",
"NET_PRICE": "20.00",
"NET_PRICE_PER_BASE_UNIT": "21.00",
"ORDER": "1",
"PRICE_INC_TAX": "24.40",
"PRICE_INC_TAX_PER_BASE_UNIT": "24.40",
"TOTAL_TIME": "Total Calculation Time: 12ms",
"VRKME": "EA",
"converted_quantity": "1.00"
}
]
}
]
this is the block of code I'm trying get the specific values but it's still not works:
public static void parseJson() {
JSONParser jsonP = new JSONParser();
try (FileReader reader = new FileReader("MyJson.json")) {
// Read JSON File
Object obj = jsonP.parse(reader);
JSONArray priceList = ((JSONArray) obj).get("outputs");
//1) getting error above line "The method get(int) in the type ArrayList is not applicable for the arguments (String)"
//2) TODO: here I want to iterate only the "MATNR", "NET_PRICE", PRICE_INC_TAX values
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
I'll be so thankful who can solve me two questions on this method!
Thanks in advance
We use the javax.json.* library for doing that kind of stuff.
try(JsonReader jsonReader = Json.createReader(new StringReader(myJsonString))) {
JsonObject jsonObject = jsonReader.readObject();
return jsonObject.getJsonArray("outputs");
// TODO: don't return something, instead iterate over array and get attributes from objects.
}
catch(Exception exception) {
// TODO: Do something with exception
}
I hope that helps.

How to combine "not" operators using the spring data Criteria builder

To setup the scene, the query I want to produce is similar to the following that I've manually written. The idea is that I want to exclude a date range from the result set. In this case, nothing from today, but if there's any in the past or in the future, I want them!
{
"createdOn": {
$not: {
"$lte": ISODate("2020-20-23T23:59:59.999999999"),
"$gte": ISODate("2020-20-23T00:00"),
}
}
}
The code I am using to try and get the above is the following:
Criteria.where("createdOn")
.not()
.gte(LocalDate.now().atTime(LocalTime.MIN))
.lte(LocalDate.now().atTime(LocalTime.MAX))
However, that generates the following:
{
"createdOn": {
"$not": {
"$gte": {
"$java": "2020-03-23T00:00"
}
},
"$lte": {
"$java": "2020-03-23T23:59:59.999999999"
}
}
}
If I changed the code to add another not before the lte it still produces the same output.
Is there any way of producing the query I want, or an alternate way of excluding a range of dates from the result set?
I tried your mongo shell and the MongoDB Spring Java code. The shell code works fine, but the corresponding Java code using the not() doesn't work (I don't know why).
Here is another way working with the same functionality your looking for:
...nothing from today, but if there's any in the past or in the future
I am using the following input documents:
{ _id: 1, createdOn: ISODate("2020-03-21T12:05:00") },
{ _id: 2, createdOn: ISODate("2020-03-28T18:33:00") },
{ _id: 3, createdOn: ISODate("2020-03-24T01:56:00") }
And, assuming today's date: ISODate("2020-03-24T02:50:04.992Z"), the result should exclude the document with _id: 3, where the createdOn is within today.
The mongo shell query:
db.collection.find( {
$or: [
{ createdOn: { $gt: ISODate("2020-03-24T23:59:59.99") } },
{ createdOn: { $lt: ISODate("2020-03-24T00:00:00") } }
]
} )
This returns the documents with _id's 1 and 2 (these exclude today's date).
The corresponding Java code:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd H:m:s");
Date fromDate = dateFormat.parse("2020-03-24 00:00:00");
Date toDate = dateFormat.parse("2020-03-24 23:59:59");
Criteria c = new Criteria().orOperator(
Criteria.where("createdOn").lt(fromDate),
Criteria.where("createdOn").gt(toDate) );
Query q = Query.query(c);
MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "testDB");
List<Document> result = mongoOps.find(q, Document.class, "collection");
result.forEach(doc -> System.out.println(doc.toJson()));

How to properly convert java object to Json (Nested)

Okay so the output I would like to get is this:
{
"id": 460,
"position": {
"x": 3078,
"y": 3251,
"z": 0
},
"random-walk": true,
"walk-radius": 1
},
But the one I currently get is:
{
"id": 460,
"position": "{
"x": 3078,
"y": 3251,
"z": 0
}",
"random-walk": true,
"walk-radius": 0
},
The problem is the position object that I am trying to convert to json.
The code I tried:
Path path = Paths.get("./npcs.json");
File file = path.toFile();
file.getParentFile().setWritable(true);
if (!file.getParentFile().exists()) {
try {
file.getParentFile().mkdirs();
} catch (SecurityException e) {
System.out.println("Unable to create directory for donator data!");
}
}
try (FileWriter writer = new FileWriter(file)) {
Gson builder = new GsonBuilder().setPrettyPrinting().create();
JsonObject object = new JsonObject();
Position pos = new Position(mob.absX, mob.absY, mob.heightLevel);
object.addProperty("id", mob.npcId);
object.addProperty("position", builder.toJson(pos));
object.addProperty("random-walk", mob.randomWalk);
object.addProperty("walk-radius", mob.walkingType);
writer.write(builder.toJson(object));
writer.close();
} catch (Exception e) {
System.out.println("Something went wrong with saving for mob !");
e.printStackTrace();
}
Does anyone has a clue on how to get the first result? So without the double-quotes.
Use this
object.add("position", new Gson().toJsonTree(pos));
instead of
object.addProperty("position", builder.toJson(pos));
result should than look like this:
"position": {
"x": 10,
"y": 50
},
JSONObject json = new JSONObject();
JSONArray addresses = new JSONArray();
JSONObject address;
try
{
int count = 15;
for (int i=0 ; i<count ; i++)
{
address = new JSONObject();
address.put("Name","Name no." + i);
address.put("Country", "Country no." + i);
addresses.put(address);
}
json.put("Addresses", addresses);
}
catch (JSONException jse)
{
out.println("Error during json formatting" + jse.getMessage());
}
I would recommend using a JSONObject for your main JSON. After that, add each of the components. For a vector, add a json array. Here is a simple example I used to understand this better.
You can use your own java objects to be precise. Gson accesses the fields in your class using reflection, so you won't have to parse anything manually.
For example in your case:
import com.google.gson.annotations.SerializedName;
public class Walk {
private int id;
private Position position;
#SerializedName("random-walk")
private boolean randomWalk;
#SerializedName("walk-radius")
private int walkRadius;
}
public class Position {
private int x,y,z;
}
Then use
Gson gson = new Gson();
Walk walk = gson.fromJson(yourJson, Walk.class);

Parsing nested JSON

I have the following JSON:
{
"registration": {
"name": "Vik Kumar",
"first_name": "Vik",
"last_name": "Kumar",
"bloodGroup": "B-",
"gender": "male",
"birthday": "10\/31\/1983",
"email": "vik.ceo\u0040gmail.com",
"cellPhone": "1234123456",
"homePhone": "1234123457",
"officePhone": "1234123458",
"primaryAddress": "jdfjfgj",
"area": "jfdjdfj",
"location": {
"name": "Redwood Shores, California",
"id": 103107903062719
},
"subscribe": true,
"eyePledge": false,
"reference": "fgfgfgfg"
}
}
I am using the following code to parse it:
JsonNode json = new ObjectMapper().readTree(jsonString);
JsonNode registration_fields = json.get("registration");
Iterator<String> fieldNames = registration_fields.getFieldNames();
while(fieldNames.hasNext()){
String fieldName = fieldNames.next();
String fieldValue = registration_fields.get(fieldName).asText();
System.out.println(fieldName+" : "+fieldValue);
}
This works fine and it print all the values except for location which is kind of another level of nesting. I tried the same trick as above code to pass json.get("location") but that does not work. Please suggest how to make it work for location.
You need to detect when you are dealing with a (nested) Object using JsonNode#isObject:
public static void printAll(JsonNode node) {
Iterator<String> fieldNames = node.getFieldNames();
while(fieldNames.hasNext()){
String fieldName = fieldNames.next();
JsonNode fieldValue = node.get(fieldName);
if (fieldValue.isObject()) {
System.out.println(fieldName + " :");
printAll(fieldValue);
} else {
String value = fieldValue.asText();
System.out.println(fieldName + " : " + value);
}
}
}
Thus, when you reach an object, such as location, you'll call the printAll recursively to print all its inner values.
org.codehaus.jackson.JsonNode json = new ObjectMapper().readTree(jsonString);
org.codehaus.jackson.JsonNode registration_fields = json.get("registration");
printAll(registration_fields);
Since location is nested within registration, you need to use:
registration_fields.get("location");
to get it. But isn't it already processed by the while-loop, why do you need to get it separately?

Categories