Jackson objectMapper gives different object for same json - java

I'm passing a json to objectmapper. The JSON string looks like this:
{
"id": "ID1",
"identifier" : "XYZ",
"data": [
{
"id": "sampleParentID",
"childrenElements": [
{
"id" : "sampleChildID",
"content" : "sample child content",
}
]
}
]
}
val objectMapper = ObjectMapper().registerModule(KotlinModule())
val obj: Object1 = objectMapper.readValue(jsonString)
My class looks something like this :
data class Object 1 (
var id : String? = null,
var identifier : String? = null,
var data: MutableList<Element>? = null,
){
// some functions
}
class Element (
var id : String?= null
var content : String? = null
var children: List<Element>? = listOf(),
) {
// som functions
}
From obj, data field is nested which is an object itself.
I want to get hashCode of data so I do obj.data.hashCode(). Let's say 12345 gets generated.
I store this in the database. Now, let's say the user sends another request with exactly the same JSON, again the JSON gets converted into an object from which I extract the data field and now when I do obj.data.hashCode(), 12345 is not generated, rather some other number gets generated.
Is this behavior expected? If yes, what is the workaround?
Update : Added classes description.

Given that your Element class is not a data class (in this case you would get a hashCode() method implementation based on all class properties) you will need to write the hashCode() method yourself so that the default one (based on object memory reference) is not used and you get rid of the behaviour you are currently facing.

Related

MongoDB nested query returning null with Java driver

I'm attempting to get the 'code' from the 'DEBIT' field from a mongodb collection formatted as follows:
"_id" : ObjectId("1"),
{...}
"bookEntryActions" : {
"CREATE" : [
{
"nature" : "DEBIT",
"code" : "123"
},
{
"nature" : "CREDIT",
"code" : "456"
}
],
"DELETE" : [
{
"nature" : "DEBIT",
"code" : "123"
},
{
"nature" : "CREDIT",
"code" : "789"
}
]
{...}
}
I've tried the following methods:
Method #1:
Document debitGlAccountCode = (Document)landlord.get("bookEntryActions.CREATE.1");
Method #2:
Document bookEntryActions = (Document) landlord.get("bookEntryActions");
Document creationRentCodes = (Document) bookEntryActions.get("CREATE");
ObjectId debitGlAccountCode = (ObjectId) creationRentCodes.get(Filters.eq("nature", "DEBIT"));
Method #3:
ObjectId debitGlAccountCode = (ObjectId) landlord.get(Filters.eq("bookEntryActions.CREATE.nature", "DEBIT"));
My issue is that of all the methods I've tried, the return for the .get("CREATE") is null. Does anyone have any idea what the issue could be? I've verified that the CREATE field exists for all of the landlords using Robo3T.
Edit: each variable has gotten the data as follows
final MongoCollection<Document> landlordCollection = db.getCollection("landlord");
final FindIterable<Document> landlordDocs = landlordCollection.find();
MongoCursor<Document> llDocIter = landlordDocs.iterator();
while(llDocIter.hasNext()){
Document landlord = llDocIter.next();
LOGGER.info("landlord bookEntryActions: " + landlord.get("bookEntryActions"));
LOGGER.info("landlord create: " + landlord.get("bookEntryActions.CREATE"));
landlordArrayList.add(landlord);
}
From there I have a foreach loop which goes through all the landlords in the arrayList and is where the previously attempted methods above are used. (Note: I'm using the array list for now as it's a little easier to work with while debugging. Eventually I will do everything in the while loop).
It turns out that the way the database was set up "CREATE" is an array list of documents and thus I had just been working with the wrong data types. Upon adapting the code to work with the arraylist and not a Document its working.

Creating model for JSON where key is a value in android

I want to create a model from JSON where key is a value. This is the exact issue described, but in iOS. I want a similar solution in Android. Basically I want to have a Decodable equivalent in Android.
I am using GSON to parse JSON to model. As of now, I have compared the JSON key (mentioned in the link) against static values.
JSON :
{
"rows" :
[
{
"_id": "5cdc0ede5c3dcb04bdb3a972",
"emp_code": 187,
"log_id": 361711,
"punch_time": "2019-05-07T04:00:33.000Z",
"pin_type": 1,
"status": 4,
"__v": 0
},
{
"_id": "5cdc40de5c3dcb04bdb3a972",
"emp_code": 111,
"log_id": 361701,
"punch_time": "2019-05-07T04:00:35.000Z",
"pin_type": 101,
"status": 4,
"__v": 0
}
],
"pin_type_text": {
"1": "In Fingerprint",
"4": "In Card",
"101": "Out Fingerprint",
"104": "Out Card"
}
}
The value of pin_type in each row refers to the record in pin_type_text mapped with it's key.
I am using GSON for creating models, and here is the model class :
class MyModel {
var length : Long = 0
var rows = ArrayList<Rows>()
var pin_type_text : String = ""
}
class PinTypeText {
var 1 : String = ""
var 4 : String = ""
var 101 : String = ""
var 104 : String = ""
}
Basically, the keys defined in class PinTypeText are the values of the key 'pin_type' obtained in Rows model as seen in the JSON shared. So in this case, the keys in 'PinTypeText' are dependent on values defined in 'rows'. Hence, i want 'PinTypeText' model to be created with respect to 'pin_type' values from 'Rows' model.
Issue : Suppose in future, the 'pin_type' values - 1, 4, 101, 104 change in the backend, how can I handle such a case without changing my model. As per this model structure, I need to change my model class every time the backend model changes
you can store the item PinTypeText as a JsonElement and not as a custom class,
so your response model will be something like this
public class Response{
#SerializedName("rows")
#Expose
private List<Row> rows = null;
#SerializedName("pin_type_text")
#Expose
private JsonElement pinTypeText;
public List<Row> getRows() {
return rows;
}
public void setRows(List<Row> rows) {
this.rows = rows;
}
public JsonElement getPinTypeText() {
return pinTypeText;
}
public void setPinTypeText(JsonElement pinTypeText) {
this.pinTypeText = pinTypeText;
}
}
and when you want to check the type you can convert it to JsonObject and get the value for the key,
example
pinTypeText= response.getPinTypeText().asJsonObject().get([your pin_type here]).toString()

Checking object as null using objectutils failed

I am using ObjectUtils.isEmpty() as generic to check for the null and empty fields.It was working fine for the term like:
MyClass class = new MyClass()
class.setName(null);
if (!ObjectUtils.isEmpty(class.getName)) {
return "Name";
}
But it is not working , when am trying it for the Object as below:
Object activatedDate = jsonObject.getJSONArray("records")
.getJSONObject(i).get("ActivatedDate");
return ObjectUtils.isEmpty(activatedDate) ? null : "hello";
and My json is:
[
{
"LastModifiedDate": "2018-05-23T10:58:18.000+0000",
"Order_Submission_Outcome__c": "test",
"Number_of_Orders__c": 0,
"Sales_Code__c": null,
"Opportunity__c": "FERERR",
"Contract_Type__c": "EZ Order Form",
"StatusCode": "Draft",
"CreatedDate": "2018-05-23T10:56:22.000+0000",
"Id": "FERERR",
"ActivatedDate": null,
"Contract_Status__c": "ACTIVE",
"Opportunity_Act_Total_Lines__c": 1
}
]
But it always returns hello even though the object activatedDate is null. What is the problem?
In JPA QL if you want to call a database function it has to be done like this:
function(‘FUNC_NAME’, param1, param2,...)

Cloudera Navigator API fail to fetch nested data

I am working in Cloudera Manager Navigator REST API where extracting result is working fine, but unable to get any nested value.
The type of data is extracting as below.
{
"parentPath": "String",
"customProperties": "Map[string,string]",
"sourceType": "String",
"entityType": "String"
}
And data should be like
{
"parentPath": "abcd",
"customProperties": {
"nameservice" : "xyz"
},
"sourceType": "rcs",
"entityType": "ufo"
}
But I am getting key-value result as follows.
parentPath :abcd
customProperties : null
sourceType : rcs
entityType : ufo
In above response data, "customProperties" is coming with a null value where it should return a map object contains ["nameservice" : "xyz"]. This is the problem with following code snippet.
MetadataResultSet metadataResultSet = extractor.extractMetadata(null, null,"sourceType:HDFS", "identity:*");
Iterator<Map<String, Object>> entitiesIt = metadataResultSet.getEntities().iterator();
while(entitiesIt.hasNext()){
Map<String, Object> result = entitiesIt.next();
for(String data : result.keySet()){
System.out.println(" key:"+data+" value:"+result.get(data));
}
}
Can you suggest me how to get the nested value where datatype is complex.
have u checked how the data looks on navigator ui? You can first verify that once, and also try cloudera /entities/entity-id rest API in browser to check how json response is coming

How to loop through JSON parameters in android

suppose I have a JSON that prints out
{"_id" :"4e3f2c6659f25a0f8400000b",
"confirmation_code":"TWLNX8BT",
"confirmed" :true,
"created_at" :"2011-08-08T00:23:02+00:00",
"email_address" :"dd5dc43ea6bf12ec604b0a7025b94105d419616b",
"first_name" :"sean",
"invites" :[],
"last_name" :"pan",
"raw_email_address":null,
**"tracking_users" :[{
"_id" :"4e407f0659f25a1ce9000007",
"active" :true,
"first_name":"Sean",
"last_name" :"Pan",
"user_id" :"4e3da65e59f25a3956000005"
},{
"_id" :"4e407f7a59f25a1d19000007",
"active" :true,
"first_name":"Sean",
"last_name" :"Pan",
"user_id" :"4e3da65e59f25a3956000005"
},{
"_id" :"4e4085c959f25a204b000004",
"active" :true,
"first_name":"Sean",
"last_name" :"Pan",
"user_id" :"4e3da65e59f25a3956000005"
}],
"updated_at" :"2011-08-08T06:44:31+00:00",
"user_id" :137141}**
in the tracking users part I have three "different" (they're the same for testing purposes) JSON strings within the original JSON. How do I go through the inner parameter (user_id[0]),(user_id[1]),(user_id[2])... of tracking_users in a for loop for android?
I am turning my JSON into a string and then using
obj = new org.json.JSONObject(response) to change it into an object then I use
String trackingusers=obj.getString("tracking_users") to get the three objects in the tracking_users variable.
Thanks
Get tracking_users as JSONArray, then loop them as JSONObject, and with the JSONObject, you can get it's properties, try this:
JSONArray tracking_users = obj.getJSONArray("tracking_users");
for (int i = 0; i < tracking_users.length(); i++) {
JSONObject user = tracking_users.getJSONObject(i);
String _id = user.getString("_id");
and etc..
}
Use getJSONArray("tracking_users") and process each item in the array as an JSONObject.
JSON is composed from Objects and Array of objects. The whole result string is an object. So you loaded it fine. After that, you have to process tracking_users as Array of Objects. So use:
JSONAeeay users = obj.getJSONArray("tracking_users");
and with this, you can cycle through the objects:
int users_count = users.length();
for (int i=0; i<users_count; i++)
{
users.getJSONObject(i)
}

Categories