Suppose I have an empty Map<String, Object> map or a Map<String, Object> map with some fields added.
In this case, I want to create a generic java method that I can set to the map I have using the values such as map, path, value type and value object that I will give as input.
The method outline I intend to create can be seen below.
public void genericJsonMapSet(Map<String, Object> jsonMap, String setPath, String setValueType, Object setValue) {
//Set JsonMap code
}
The json representation of the map before and after the following calls of the method to be created should be as follows.
genericJsonMapSet(jsonMap, "setid()", "string", "a9a9940d-593f-4546-8065-6d70370d9f64");
genericJsonMapSet(jsonMap, "setrequestDate()", "string", "2022-10-10 16:20:15");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setvalueType()", "string", "string");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setname()", "string", "username");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setvalue()", "string", "taner.turan");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setvalueType()", "string", "integer");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setname()", "string", "id");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setvalue()", "integer", "23");
Before:
{
}
After:
{
"id": "a9a9940d-593f-4546-8065-6d70370d9f64",
"requestDate": "2022-10-10 16:20:15",
"userCharacteristic": [
{
"valueType": "string",
"name": "username",
"value": "taner.turan"
},
{
"valueType": "integer",
"name": "id",
"value": 23
}
]
}
Can anyone provide code for this?
This project works similarly. I wrote it.. a long long time ago, as far as I know nobody uses it. Map<String, Object> is not java-like at all; there is almost no purpose to such a thing. I encapsulated the notion into a JSON object instead. Also, you don't use strings to 'set' things, again, un-java like. Thus, this code:
Map<String, Object> jsonMap = new HashMap<>();
genericJsonMapSet(jsonMap, "setid()", "string", "a9a9940d-593f-4546-8065-6d70370d9f64");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setvalueType()", "string", "string");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setvalue()", "integer", "23");
Becomes:
JSON j = JSON.newMap();
j.get("setId").setString("a9a9940d-593f-4546-8065-6d70370d9f64");
j.get("setuserCharacteristic").add().setString("string");
j.get("setuserCharacteristic").get(2).setInteger(23);
add() is the same as .get(i) where i is one larger than whatever is there already. You can get non-existent things; they are created automatically once you .set anywhere in the 'chain'. i.e.:
JSON j = JSON.newMap();
j.get("foo").get("bar").setString("hello");
Gives you JSON structure:
{
"foo": {
"bar": "hello"
}
}
Link to code on github
You can make use of the function unflatten() of library Josson to do what you want.
https://github.com/octomix/josson
Josson josson = Josson.create();
josson.put("id", "a9a9940d-593f-4546-8065-6d70370d9f64");
josson.put("requestDate", "2022-10-10 16:20:15");
josson.put("userCharacteristic[1].valueType", "string");
josson.put("userCharacteristic[1].name", "username");
josson.put("userCharacteristic[1].value", "taner.turan");
josson.put("userCharacteristic[2].valueType", "integer");
josson.put("userCharacteristic[2].name", "id");
josson.put("userCharacteristic[2].value", 23);
JsonNode node = josson.getNode("unflatten('.[]')");
System.out.println(node.toPrettyString());
Output
{
"id" : "a9a9940d-593f-4546-8065-6d70370d9f64",
"requestDate" : "2022-10-10 16:20:15",
"userCharacteristic" : [ {
"valueType" : "string",
"name" : "username",
"value" : "taner.turan"
}, {
"valueType" : "integer",
"name" : "id",
"value" : 23
} ]
}
Related
How can I compare two JSON, one I get from the database and the second One from FrontEnd(means when I click on the edit button)? How can I compare these two JSON?
First Json
{
"id": 2,
"createdAt": "07-01-2021 15:26:16",
"updatedAt": "07-01-2021 15:26:16",
"offerAcceptedDate": "06-30-2021 07:14:00",
"offerAmount": 100000,
"offerDate": "06-30-2021 07:14:00",
"offerFile": "string",
"possibleCloseDate": "06-30-2021 07:14:00",
"remarks": "string",
"salesId": 8,
"status": "Active",
"contactId": 32,
"createdById": 1,
"offerAcceptedById": 1
}
2nd JSON
{
"createdAt": "09-01-2021 15:26:16",
"updatedAt": "10-01-2021 15:26:16",
"offerAcceptedDate": "06-30-2021 07:14:00",
"offerAmount": 500000,
"offerDate": "06-30-2021 07:14:00",
"offerFile": "string",
"possibleCloseDate": "06-30-2021 07:14:00",
"remarks": "string",
"salesId": 8,
"status": "Active",
"contactId": 32,
"createdById": 1,
"offerAcceptedById": 1
}
Also, compare these two JSON and also show activity what column" changed.
Like this:
createdAt: Changed
updatedAt: Changed
offeramount: Changed
1)First of all I get data from DB using findById(JPA Repository)
2)Compare Db field and request body field
like that :
LeadOffer leadOffer = leadOfferRepository.findById(offerId).orElse(null);
JsonObject jsonObject = new JsonObject();
JsonArray jsonArray= new JsonArray();
if (leadOffer.getAmount() != leadOfferRequest.getAmount())
{
offer.setAmount(leadOfferRequest.getAmount());
jsonObject.addProperty("amount",leadOfferRequest.getAmount() );
jsonObject1.addProperty("amount",leadOffer.getAmount() );
}
jsonArray.add(jsonObject);
You can use guava library for this purpose. For example :
String json1 = "{\"name\":\"ABC\", \"city\":\"XYZ\", \"state\":\"CA\"}";
String json2 = "{\"city\":\"XYZ\", \"street\":\"123 anyplace\", \"name\":\"ABC\"}";
Gson g = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> firstMap = g.fromJson(json1, mapType);
Map<String, Object> secondMap = g.fromJson(json2, mapType);
System.out.println(Maps.difference(firstMap, secondMap).entriesDiffering());
This shows the keys that are present in both the maps but have different values
I have a JSON object that contains undetermined pattern and I need to get all keys of the json object and the sub-objects.
Here's an example of a JSON file:
{
"users": {
"address": [
{
"rue": "ruetest",
"postal": 1111
},
{
"rue": "ruetest",
"postal": 2222
}
],
"type": "string",
"user": [
{
"argent": 122,
"id": 1,
"nom": "user1",
"prenom": "last1"
},
{
"argent": 200,
"id": 2,
"nom": "user2",
"prenom": "last2"
},
{
"argent": 1205,
"id": 3,
"nom": "user3",
"prenom": "last3"
}
]
}
}
and I need to have output like this:
[users,type,address,user,argent,id,nom,prenom] or something like this
I don't think there's really a built-in way to do this, but you could achieve your goal by making a function that does it. Something like (in pseudocode):
public Set getJsonKeys(JSON json) {
Set s = new Set();
for (Entry e : json.entrySet()) {
s.add(e.key);
if (e.value instanceof JSON) s.addAll(getJsonKeys(e.value));
}
return s;
}
I chose a Set rather than List to prevent duplicate entries. If you want to include keys of lists just add a check if e.value is a list and if so, iterate over elements and add getJsonKeys(element) for all elements.
Have you tried the Genson Java Collections mode?
It would give you easy generic access to arbitrary JSON files in java.
If you use the fastjson framework, I think you can use the following code to get all the keys:
JSONObject jsonObject = new JSONObject(jsonData);
Iterator keys = jsonObject.keys();
while (keys.hasNext()){
String key = String.valueOf(keys.next());
}
I am currently working on elastic search through my java Application . I know how to index the Java pojo using RestHighLevelClient. How i can make search only on new fields not the complete pojo.?
public class Employee{
private long id;
private String name;
private String designation;
private String address; //want to index but not searchable in elastic search
}
My Code for indexing is below which is working fine:
public String saveToEs(Employee employee) throws IOException {
Map<String, Object> map = objectMapper.convertValue(employee, Map.class);
IndexRequest indexRequest =
new IndexRequest(INDEX, TYPE, employee.getId().toString()).source(map, XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
I need to do this in java .Any help please or good link ?
Writing another answer for RestHighLevelClient As another answer is useful for people not using the Rest client and adding this in the first answer makes it too long.
Note: you are passing the type which is deprecated in ES 7.X and I am using the ES 7.X version, so my code is according to 7.X.
CreateIndexRequest request = new CreateIndexRequest("employee");
Map<String, Object> name = new HashMap<>();
name.put("type", "text");
Map<String, Object> address = new HashMap<>();
address.put("type", "text");
address.put("index", false);
Map<String, Object> properties = new HashMap<>();
properties.put("name", name);
properties.put("address", address);
Map<String, Object> mapping = new HashMap<>();
mapping.put("properties", properties);
request.mapping(mapping);
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
Important points
I've used only 2 fields for illustration purpose, one of which is address field which is not searchable, and to do that I used, address.put("index", false); , while name is searchable field and there this option isn't present.
I've created index mapping using the Map method which is available in this official ES doc.
you can check the mapping created by this code, using mapping REST API.
Below is the mapping generated for this code in my system and you can see, index: false is added in the address field.
{
"employee": {
"mappings": {
"properties": {
"address": {
"type": "text",
"index": false
},
"name": {
"type": "text"
}
}
}
}
}
You can just use the same search JSON mentioned in the previous answer, to test that it's not searchable.
Use the index option as false on the address field, which is by default true to make it unsearchable. As mention in the same official ES link:
The index option controls whether field values are indexed. It accepts
true or false and defaults to true. Fields that are not indexed are
not queryable.
Let me show you how can you test it using the REST API and then the java code(using rest-high level client) to accomplish it.
Mapping
{
"mappings": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text"
},
"designation": {
"type": "text"
},
"address": {
"type": "text",
"index" : false --> made `index` to false
}
}
}
}
Index few docs
{
"address" : "USA",
"name" : "Noshaf",
"id" : 234567892,
"designation" : "software engineer"
}
{
"address" : "USA california state",
"name" : "opster",
"id" : 234567890,
"designation" : "software engineer"
}
A simple match search query in JSON format on address field
{
"query": {
"match" : {
"address" : "USA"
}
}
}
Exception from Elasticsearch clearly mention, it's not searchable
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Cannot search on field [address] since it is not indexed."
}
We wanted to create a JSON structure as below in Java
{
[
{
"key": "ABC001",
"value": true
},
{
"key": "ABD12",
"value": false
},
{
"key": "ABC002",
"value": true
},
]
}
To implement this we created a class and had a list private property inside it.
But that is creating a key values
class Response{
private List<Property> values;
// setter getter for this private property
}
The output for this is
{
values : [
{
"key": "ABC001",
"value": true
},
......
]
Is there a way we create the array without the key and inside the { }?
Unfortunately, what you're trying to build is not a valid json.
You can try to validate it here.
With this "json", for example, it would be impossible to read the array, because it has no key.
{
"foo_key" : "bar",
[
{
"key": "ABC001",
"value": true
},
{
"key": "ABD12",
"value": false
},
{
"key": "ABC002",
"value": true
},
]
}
Parsing a json like this one, you could get "bar" because it has a key ("foo_key"), but how could you get the array?
The code you're using is already correct for a valid json.
So, for some reason you want an invalid json, which is an array contained between {}s. Here's how you can do it (I'll assume you use google-gson to make and parse jsons, since you didn't include your code):
// example of the creation of the list
List<Property> values = new ArrayList<>();
values.add(new Property("ABC001", true));
values.add(new Property("ABD12", false));
values.add(new Property("ABC002", true));
//
Gson gson = new Gson();
String json = gson.toJson(values, new TypeToken<List<Property>>() {}.getType());
json = "{" + json + "}";// gotta do what you gotta do...
I have a schema like this (simplified):
{
"range": {
"offset": 0,
"limit": 1,
"total": 2
},
"items": [
{
"id": 11,
"name": "foo",
"children": [
{
"id": 112,
"name": "bar",
"children": [
{
"id": 113,
"name": "foobar",
"type": "file"
}
],
"type": "folder"
},
{
"id": 212,
"name": "foofoo",
"type": "file"
}
],
"type": "room"
},
{
"id": 21,
"name": "barbar",
"type": "room"
}
]
}
I need to read only specific values like "id" from the first room (item). For this I need to iterate trough all items on every level (n items for root, n items for n children) with type folder or file.
For now i have this code:
POJO
public static class Item {
public int id;
}
Jackson Tree Iteration
ObjectMapper mapper = new ObjectMapper();
com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(JSON);
root = root.get("items").get(0);
TypeReference<List<Item>> typeRef = new TypeReference<List<Item>>(){};
List<Item> list = mapper.readValue(root.traverse(), typeRef);
for (Item f : list) {
System.out.println(f.id);
}
How can i get all id's of all children in all items with specific type?
How to avoid the "Unrecognized field" exception without defining the whole schema?
Thank you very much for your help!
Try using java8 functions it has lot to do it in lesser lines ,
ObjectMapper mapper = new ObjectMapper();
Pass your json value
Map obj = mapper.readValue(s, Map.class);
List<Object> items= (List<Object>) obj.get("items");
Object[] Ids= items
.stream()
.filter(items-> ((Map)items).get("type").equals("room"))
.toArray()
Use the readTree(...) method to parse the JSON without needing to define the entire schema and find Nodes called "id".
You can then use findValues("id") to get the List of values back.