I use swagger-maven-plugin to generate swagger.json. However, I noticed that an order of properties changes from run to run. For example, it can be:
{
...
"definitions" : {
"MyClass1" : {
"type" : "object",
"properties" : {
"name" : {
"type" : "string"
},
"title" : {
"type" : "string"
},
"description" : {
"type" : "string"
},
}
}
}
...
}
and then after the next generation:
{
...
"definitions" : {
"MyClass1" : {
"type" : "object",
"properties" : {
"description" : {
"type" : "string"
},
"title" : {
"type" : "string"
},
"name" : {
"type" : "string"
}
}
}
}
...
}
My class in Java:
public interface MyClass1 {
String getName();
String getTitle();
String getDescription();
}
It's impossible in Java Runtime to know the exact order of methods declared in a class. If you open java.lang.Class#getDeclaredMethods() (see https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethods--) you will see that The elements in the returned array are not sorted and are not in any particular order..
That's why Jackson can't do it for you.
However, there are 2 solutions:
1.You can use #JsonPropertyOrder annotation:
#JsonPropertyOrder({"name", "title", "description"})
public interface MyClass1 {
String getName();
String getTitle();
String getDescription();
}
2.You can use a class with fields (field order is preserved)
public class MyClass1 {
String name;
String title;
String description;
//Getters skipped
}
Related
I am working with Mongo aggregation/filter/sorting and limit with JAVA.
I have below model objects. CustomPOJO is my database collection.
#Document(collation = "CustomPOJO")
public class CustomPOJO {
public List<KeyValueObject> valueList;
public String attribute1;
public String attribute2;
public CustomObject attribute3;
}
public class CustomObject {
public String attribute4;
public String attribute5;
}
public class KeyValueObject {
public String name;
public String value;
}
Now I have entries in my DB with below records
Record1:
{
"valueList": [{
"name": "field1",
"value": "value1"
}, {
"name": "field2",
"value": "value2"
}, {
"name": "field3",
"value": "value3"
}],
"attribute1": "attribute1",
"attribute2": "attribute2",
"attribute3": {
"attribute4": "attribute4",
"attribute5": "attribute5"
}
}
Record2:
{
"valueList": [{
"name": "field1",
"value": "value4"
}, {
"name": "field2",
"value": "value5"
}, {
"name": "field3",
"value": "value6"
}],
"attribute1": "attribute11",
"attribute2": "attribute22",
"attribute3": {
"attribute4": "attribute44",
"attribute5": "attribute55"
}
}
I am able to do sort on all fields using sort(DESC,"attribute1") or sort(DESC,"attribute3.attribute4") or sort(DESC,"attribute2"). But i am unable to sort on valueList. I want to do sort according to specific KeyValue entry inside of valueList.
For example record1 have valueList with entry field1 so all records in DB should sort according field1 and value inside it.
In general i want to sort on field inside of list attribute.
Any help will be highly appreciate.
You can't sort using array's key value pair in place. You could use aggregation framework.
Project the document matching key entry followed by sort on the value and remove the additional field from the document.
Something like
db.collection.aggregate(
[
{"$set":{
"sortdoc":{
"$arrayElemAt":[
{
"$filter":{
"input":"$valueList",
"cond":{"$eq":["$$this.name","field1"]}
}
},0]}
}},
{"$sort":{"sortdoc.value":-1}},
{"$project":{"sortdoc":0}}
])
https://mongoplayground.net/p/gzLQm8m2wQW
You could also model valueList as object just the way you have for attributes. Use Document class or HashMap instead of List of values and use sort(DESC,"document.field1")
#Document(collation = "CustomPOJO")
public class CustomPOJO {
public Document document;
public String attribute1;
public String attribute2;
public CustomObject attribute3;
}
Document
{
"document": {
"field1": "value1",
"field2": "value2"
},
"attribute1": "attribute1",
"attribute2": "attribute2",
"attribute3": {
"attribute4": "attribute4",
"attribute5": "attribute5"
}
}
You cannot sort documents on fields inside of Arrays directly. Generally what i do is unwind the array and then perform sort.
May be this is something that may help you.
db.collection.aggregate([
{
"$unwind": "$valueList"
},
{
"$sort": {
"valueList.name": -1
}
}
])
Mongo Playground
So My problem is related to how spring handles inheritance when it comes to fields.
I have four classes
#Document(collection = "A")
public class A {
#Id
id;
#Field
B data;
}
public class B {
Type type
}
public class C extends B {
String cField;
public C() {
super(Type.C);
}
}
public class D extends B {
Integer dField;
public D() {
super(Type.D);
}
}
I'm able to store data into mongodb using this schema and it looks something like this
{
"_id" : ObjectId("5f291f861020d19a3db05123"),
"data" : {
"cField" : "abcd",
"type" : "C",
"_class" : "com.example.C"
},
"_class" : "com.example.A"
}
{
"_id" : ObjectId("5f291f861020d19a3db05124"),
"data" : {
"dField" : NumberInt(30),
"type" : "D",
"_class" : "com.example.D"
},
"_class" : "com.example.A"
}
Now when I try to do a findAll on repository, it does not casts to the child class, but simply returns an instance of B.
What changes do I need to make so that I can get correct child object when getting from db?
I have a Java list representation like below
List representation of data
[
{ "type" : "Error", "name" : "xyz" },
{ "type" : "Success", "name" : "abc" },
{ "type" : "none", "name" : "prq" },
{ "type" : "Success", "name" : "" },
{ "type" : "Success", "name" : "xyz" },
{ "type" : "Warning", "name" : "efc" }
.
.
.
]
(Partial representation here).
and an Object representation below
public Node {
List<String> errorNames;
List<String> SuccessNames;
List<String> WarningNames;
}
I want to use Java streams to separate the three type of names based on their type and add each name to the respective Lists.
What will be the best way (Stream.filter/Collect/Map anything else) to split the list such that at the end "Node's->(all the lists)" will have corresponding data?
Assuming your Node class actually looks something like this:
public class Node {
private String type;
private String name;
public Node(String type, String name) {
this.type = type;
this.name = name;
}
public String getType() {
return type;
}
public String getName() {
return name;
}
}
You can use Collectors#groupingBy in combination with Collectors#mapping to create a Map<String, List<String>> where they key is the type and the value are the List of name for every Node of that type:
var nodes = List.of(
new Node("Error", "xyz"), new Node("Success", "abc"),
new Node("none", "prq"), new Node("Success", ""),
new Node("Success", "xyz"), new Node("Warning", "efc")
);
var map = nodes.stream()
.collect(Collectors.groupingBy(Node::getType,
Collectors.mapping(Node::getName, Collectors.toList())));
System.out.println(map);
Output:
{Warning=[efc], Error=[xyz], none=[prq], Success=[abc, , xyz]}
My repository implements the following interface:
QueryDslPredicateExecutor<Rule>
The structure of mongo's document(Rule object) is:
{
"_id" : ObjectId("5aa924242a73bec4ce581717"),
"name" : "test-name",
"expressionGroups" : [
{
"type" : "WHEN",
"expressions" : [
{
"name" : "name1",
"values" : ["VAL1", "VAL2", "VAL3"]
},
{
"name" : "name2",
"values" : ["VAL4", "VAL5"]
}
]
},
{
"type" : "FOR",
"expressions" : [
{
"name" : "name3",
"values" : ["VAL6", "VAL7"]
}
]
}
]
}
I want to use the following method to find particular rule within mongodb:
Iterable<T> findAll(Predicate predicate);
I've prepared mongo shell query:
db.rule.find({
'expressionGroups.expressions': {
$all: [
{
'$elemMatch': {
'name': "name1",
'values': "VAL2"
}
},
{
'$elemMatch': {
'name': "name3",
'values': "VAL7"
}
}
]
}
}).pretty()
How can I create com.querydsl.core.types.Predicate based on above query?
There is still no answer and I've met the same issue. So I created such code:
private List<Predicate> toPredicates(String root, Map<String, Object> map) {
List<Predicate> predicates = new ArrayList<>();
for (Map.Entry<String, Object> entry: map.entrySet()) {
String path = root+'.'+entry.getKey();
Object value = entry.getValue();
if (entry.getValue() instanceof Map) {
predicates.addAll(toPredicates(path, (Map<String, Object>) value));
} else {
predicates.add(new SimplePath(path).eq(value.toString()));
}
}
return predicates;
}
private static class SimplePath extends StringPath {
protected SimplePath(String var) {
super(var);
}
}
So, you can parse Json to Map and this is it.
I got a problem so I'm using the google places api.
I will not write the whole code here because it's too big. But this is what I get for resuls whenever I call the google api:
{
"html_attributions" : [],
"result" : {
"address_components" : [
{
"long_name" : "48",
"short_name" : "48",
"types" : [ "street_number" ]
},
{
"long_name" : "Pirrama Road",
"short_name" : "Pirrama Road",
"types" : [ "route" ]
},
{
"long_name" : "Pyrmont",
"short_name" : "Pyrmont",
"types" : [ "locality", "political" ]
},
{
"long_name" : "NSW",
"short_name" : "NSW",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "AU",
"short_name" : "AU",
"types" : [ "country", "political" ]
},
{
"long_name" : "2009",
"short_name" : "2009",
"types" : [ "postal_code" ]
}
],
"events" : [
{
"event_id" : "9lJ_jK1GfhX",
"start_time" : 1293865200,
"summary" : "<p>A visit from author John Doe, who will read from his latest book.</p>
<p>A limited number of signed copies will be available.</p>",
"url" : "http://www.example.com/john_doe_visit.html"
}
],
"formatted_address" : "48 Pirrama Road, Pyrmont NSW, Australia",
"formatted_phone_number" : "(02) 9374 4000",
"geometry" : {
"location" : {
"lat" : -33.8669710,
"lng" : 151.1958750
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "4f89212bf76dde31f092cfc14d7506555d85b5c7",
"international_phone_number" : "+61 2 9374 4000",
"name" : "Google Sydney",
"rating" : 4.70,
"reference" : "CnRsAAAA98C4wD-VFvzGq-KHVEFhlHuy1TD1W6UYZw7KjuvfVsKMRZkbCVBVDxXFOOCM108n9PuJMJxeAxix3WB6B16c1p2bY1ZQyOrcu1d9247xQhUmPgYjN37JMo5QBsWipTsnoIZA9yAzA-0pnxFM6yAcDhIQbU0z05f3xD3m9NQnhEDjvBoUw-BdcocVpXzKFcnMXUpf-nkyF1w",
"reviews" : [
{
"aspects" : [
{
"rating" : 3,
"type" : "quality"
}
],
"author_name" : "Simon Bengtsson",
"author_url" : "https://plus.google.com/104675092887960962573",
"text" : "Just went inside to have a look at Google. Amazing.",
"time" : 1338440552869
},
{
"aspects" : [
{
"rating" : 3,
"type" : "quality"
}
],
"author_name" : "Felix Rauch Valenti",
"author_url" : "https://plus.google.com/103291556674373289857",
"text" : "Best place to work :-)",
"time" : 1338411244325
},
{
"aspects" : [
{
"rating" : 3,
"type" : "quality"
}
],
"author_name" : "Chris",
"text" : "Great place to work, always lots of free food!",
"time" : 1330467089039
}
],
"types" : [ "establishment" ],
"url" : "http://maps.google.com/maps/place?cid=10281119596374313554",
"vicinity" : "48 Pirrama Road, Pyrmont",
"website" : "http://www.google.com.au/"
},
"status" : "OK"
}
Now I all save that here:
package com.androidhive.googleplacesandmaps;
import java.io.Serializable;
import com.google.api.client.util.Key;
/** Implement this class from "Serializable"
* So that you can pass this class Object to another using Intents
* Otherwise you can't pass to another actitivy
* */
public class Place implements Serializable {
#Key
public String id;
#Key
public String name;
#Key
public String reference;
#Key
public String icon;
#Key
public String vicinity;
#Key
public Geometry geometry;
#Key
public String formatted_address;
#Key
public String formatted_phone_number;
#Override
public String toString() {
return name + " - " + id + " - " + reference;
}
public static class Geometry implements Serializable
{
#Key
public Location location;
}
public static class Location implements Serializable
{
#Key
public double lat;
#Key
public double lng;
}
}
Here is how I get the results:
public class PlacesList implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Key
public String status;
#Key
public List<Place> results;
}
Now my question is:
In the result i get from google you can see the photo_reference. But it's an array and I just need to have the first photo_reference. How can I get that in my code?
JSONObject res = // your google api results
JSONArray photos = res.getJSONArray("photo_reference"); // Extract the JSONArray
// Get the item at index 0, which should be a reference to the first image
String photo = photos.getString(0);
This will get you the reference to the photo, then it looks like you have to make another request to the Photo API.
https://maps.googleapis.com/maps/api/place/photo?parameters
For more information on how to use the Photo API, look at https://developers.google.com/places/documentation/photos