I am new to android realm.
I am using follwing code to get product object from realm.
ProductModel prodObj = realm.where(ProductModel.class).equalTo("product_id","12").findFirst();
How can i create standalone copy of prodObj?
I want to update some field's value that should not affect in realm database. I don't want to set it manually with setters method because model class contains too many fields. Is there any easy way to create standalone copy of prodObj?
Since 0.87.0
Added Realm.copyFromRealm() for creating detached copies of Realm objects (#931).
Realm only has a copyToRealm method and not a copyFromRealm method. Currently, there is a number of restriction to model classes (see https://realm.io/docs/java/latest/#objects) but we are investigating and experimenting how to lift these.
We have an open issue about exactly what you are asking: https://github.com/realm/realm-java/issues/931. But for the time being, you will have to copy our objects manually.
In case anyone wondered like me how we can implement this copyFromRealm(), this is how it works:
ProductModel prodObj = realm.where(ProductModel.class)
.equalTo("product_id", "12")
.findFirst();
ProductModel prodObjCopy = realm.copyFromRealm(prodObj);
You can serialize an object into a JSON string and deserialize into a standalone object by Jackson like:
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(yourObject);
objectMapper.readValue(json, YourModel.class);
GSON might not work because it doesn't support getter/setter when it makes a JSON.
I know it's a horrible solution.
But it might be the only way yet.
Related
I'm a bit confused, as from a long time i am saving the json response directly to an ArrayList> and displaying to my listView, but now, looking on other people code i noticed that they are using POJO class to interact with JSON, Is it is better way? if it is please explain why? cause using POJO means I have to write extra code, But if saving the response directly to the arraylist make my work done, then why should i use a POJO class?
So, Pojo usage better due to OOP pattern, because you work at runtime with your Java object without intermediate Json parse. Manual json parsing too ugly due to code style(its my opinion).
But if saving the response directly to the arraylist make my work done
If, you collect your object in Maps, you can apply different features out of the box(sort, compare etc) to your map, but in case when your map contains POJO instead of JSONS.
Encapsulation. When you work with dates for examples or with type, its pretty good to use getters/setters for data mapping instead of manual parsing again and again.
4.Object scaling and mapping:
Lets image that we have some object user:
public class User{
int id;
#SerializedName("specific_id_for_blah_blah")
private int mSpecId
#SerializedName("date_of_birthaday")
private String mBDay;
public Date getBirthday() {
return new Date(mBDay);
}
}
What I want to say by this example.
You can map your json to POJO with one line of code only
User user = new Gson.fromJson(response, User.class);
Pretty simple isn't?.
Name serialization. When your response contain key name which looks to long or weird, you can use your own style naming with easy changes, just with small annotation. mSpecId returns value of "specific_id_for_blah_blah"
Platform specific encapsulation. You can use only platform specific object at your runtime, instead parsing operations in your business logic. String with data -> Date or Calendar
Also you can override Object methods in your POJO (equals, hashcode, toString) for your logic spec. operations.
If your serverside change some key you can change name of key in POJO instead looking through where you parse it before. IN same case you can add new field and setter/getter, if some of parameter will be added to your response
There is no right and wrong answer here. It all depends on your use case. If your solution works, and you are happy with it, I don't see why do you need to change it.
If I had to choose, I would go with a POJO class to represent the response, but this is a subjective opinion. I think that you have the following benefits:
It's cleaner - having a separate, dedicated class to represent your payload gives you the ability to be more specific in your code. You are no longer manipulating Maps of key - value pairs, but instances of a specific class, that can have a more specific behaviour. You can specify natural ordering, criteria for equality, etc - things that may be useful for your program's logic
It's simpler - I would prefer calling a getter every time then accessing a map by a property name and getting an Object back. The logic of the program will be much simpler and safer.
It's better in terms of OOP best practices - the whole point behind OOP is to have objects, that define properties and behaviours. IMHO, using POJOs to represent responses forces you to adhere more closely to best practices.
There are also some cases that will fit the no - POJO approach better - for example, if you only display your data, not manipulating it in any way inside the app. Or if you want to shave off some time for the complex parsing that may be needed if you are trying to inflate object hierarchies.
My best suggestion is - profile your app, check your use cases and make an educated decision which approach is better.
I was wondering if somewhere out there exists a java library able to query a JSONObject. In more depth I'm looking for something like:
String json = "{ data: { data2 : { value : 'hello'}}}";
...
// Somehow we managed to convert json to jsonObject
...
String result = jsonObject.getAsString("data.data2.value");
System.out.println(result);
I expect to get "hello" as output.
So far, the fastest way I have found is using Gson:
jsonObject.getAsJsonObject("data").getAsJsonObject().get("data2").getAsJsonObject("value").getAsString();
It's not actually easy to write and read. Is there something faster?
I've just unexpectedly found very interesting project: JSON Path
JsonPath is to JSON what XPATH is to XML, a simple way to extract parts of a given document.
With this library you can do what you are requesting even easier, then my previous suggestion:
String hello = JsonPath.read(json, "$.data.data2.value");
System.out.println(hello); //prints hello
Hope this might be helpful either.
While not exactly the same, Jackson has Tree Model representation similar to Gson:
JsonNode root = objectMapper.readTree(jsonInput);
return root.get("data").get("data2").get("value").asText();
so you need to traverse it step by step.
EDIT (August 2015)
There actually is now (since Jackson 2.3) support for JSON Pointer expressions with Jackson. So you could alternatively use:
return root.at("/data/data2/value").asText();
First of all, I would recommend consider JSON object binding.
But in case if you get arbitrary JSON objects and you would like process them in the way you described, I would suggest combine Jackson JSON processor along with Apache's Commons Beanutils.
The idea is the following: Jackson by default process all JSON's as java.util.Map instances, meanwhile Commons Beanutils simplifies property access for objects, including arrays and Map supports.
So you may use it something like this:
//actually it is a Map instance with maps-fields within
Object jsonObj = objectMapper.readValue(json, Object.class);
Object hello = PropertyUtils.getProperty(jsonObj, "data.data2.value")
System.out.println(hello); //prints hello
You can use org.json
String json = "{ data: { data2 : { value : 'hello'}}}";
org.json.JSONObject obj = new org.json.JSONObject(json);
System.out.println(obj.query("/data/data2/value"));
I think no way.
Consider a java class
class Student {
Subject subject = new Subject();
}
class Subject {
String name;
}
Here if we want to access subject name then
Student stud = new Student();
stud.subject.name;
We cant access name directly, if so then we will not get correct subject name. Like here:
jsonObject.getAsJsonObject("data")
.getAsJsonObject()
.get("data2")
.getAsJsonObject("value")
.getAsString();
If you want to use same like java object then use
ClassName classObject = new Gson().fromJson(JsonString, ClassName.class);
ClassName must have all fields to match jsonstring. If you have a jsonobject inside a jsonobject then you have to create separate class like I'm doing in Student and Subject class.
Using Java JSON API 1.1.x (javax.json) one can make use of new JavaPointer interface. Instance implementing this interface can be considered to some extend as kind of XPath expression analog (see RFC-6901 for details). So in your case you could write this:
import javax.json.*;
//...
var jp = Json.createPointer("/data/data2/value");
System.out.println(jp.getValue(jsonObject));
In 1.1.4 version of JSON there's also nice addition to JsonStructure interface (which is implemented by JsonObject and JsonArray), namely getValue(String jsonPointer). So it all comes down to this simple one-liner:
System.out.println(jsonObject.getValue("/data/data2/value"));
We can use gson for parsing JSON response and save our time. I have used this in numerous projects. What question came in my mind is even if we declare variable final, gson can fill that variables value.
Now this something strange and conflicting with OOP principals. How can any other thing except that class can access those private variables?
Is there any principal or concept which does this, probably as a part of Serialization or something like that ?
Also one more thing, in case of making it Parcelable we always have one parameterised constructor. At that time how Gson can create object of our class in absence of default constructor?
Gson is using Java "Reflection" for accessing the private fields of other class.
This question already has answers here:
Cannot retrieve field values from realm object, values are null in debugger
(5 answers)
Closed 5 years ago.
When doing find queries for objects I'm getting "empty" objects (non-null, but not populated). However, in the debugger I can see the data for the object in the object description (see below). I've also verified the data is there using the Realm Browser. I've tried different find queries, querying with filter criteria, using the same Realm object for inserts/queries, using different Realm objects for inserts/queries, refreshing the Realm, etc.
If I Log fields in the RealmObject I see the proper data print out. However, I'm trying to convert these models into other models for use in RxJava per https://realm.io/news/using-realm-with-rxjava/.
Here's some sample code where reproduced the issue. Below that is a screenshot when breaking at verifyRealm.close().
RealmTester realmTester1 = new RealmTester();
realmTester1.setFirstName("Tester1");
realmTester1.setLastName("ABC");
RealmTester realmTester2 = new RealmTester();
realmTester2.setFirstName("Tester2");
realmTester2.setLastName("XYZ");
Realm insertRealm = Realm.getDefaultInstance();
insertRealm.refresh();
insertRealm.beginTransaction();
insertRealm.copyToRealm(realmTester1);
insertRealm.copyToRealm(realmTester2);
insertRealm.commitTransaction();
insertRealm.close();
Realm verifyRealm = Realm.getDefaultInstance();
RealmResults<RealmTester> verifyTesters = verifyRealm.where(RealmTester.class).findAll();
verifyRealm.close();
I have a screenshot of the debugger at: http://i.stack.imgur.com/1UdRr.png
I'm using v0.82.1. Any thoughts on why the models here aren't populating?
The idea behind realm-java is that we are generating Proxy class inherits from user's model class, and override the setters and getters there.
It is totally normal that you see null values for the model's field in the debugger, since the Realm are not setting them. (zero-copy, Realm is trying to reduce the memory usage by managing the data in the native code and sharing them whenever it is possible.)
Because of this, when you want to access a Realm model's field, please always use setters and getters. Checking the generated Proxy class will help you to understand this, it is quite simple actually. It is located in the build directory named like MyModelRealmProxy.java
And also check this section of the documents, it would give you some idea about the standalone object and how to write them to Realm.
I have a large json page which contains url:http://akhilmadanan.tk/Akhil/database.php.
While i am parsing this page using normal json parsing method it shows "OutOfMemoryError". For this i heard about GSON. Please any body help me get how to read the datas from below page using GSON.
any tutorial?
Here'a good tutorial:
http://www.javacodegeeks.com/2011/01/android-json-parsing-gson-tutorial.html
You can also check out their official user guide:
https://sites.google.com/site/gson/gson-user-guide
Hope this helps :-)
Instead of returning all the data, why don't you break it into chunks? That would require less memory at processing time.
Thats assuming you have access to the database level/response.
You can definitely go to links provided by others which are helpful
For brief you can add GSON library in your lib folder.
and use like this.
Gson gson=new Gson();
To get object from json
Model model=gson.fromJson(json,Model.class);
To convert to json
String json=gson.toJson(model);
I run your code and there are 3010 items of object
[
{
"cust_no":"70105615002",
"cust_name":"akhil",
"address":"kajffjkhfhhkjsd",
"area":"58695",
"ranges":"4586",
"plot":"69896",
"multifactor":"85758",
"electricity_meterno":"7895",
"water_meterno":"69358",
"gas_metrno":"78956",
"traffic_code":"4587855",
"last_meter":"58695",
"previous_reading":"25638",
"date":"589687",
"current_usage":"789654",
"current_balance":"45876",
"last_recipt":"236584"
},....
Now make a model equivalent to above name like
#SerializedName("cust_no")
private Long custNo;
#SerializedName("cust_name")
private Long custName;
..........
remember to add one list of same class type like
#SerializedName("custname")
private List<Customer> customerList;
and generate getters and setters of that Customer class;
after this
parse your data like this
CustomerModel customerModel=gson.fromJson(json,Customer.class);
you get all your data in customerModel;
To access data just use list of that class.
List<Customer> customerList=customerModel.getCustomerList();
Log.v("APP_NAME",""+customerList.size());