is it possible to set default value using annotations in gson? - android

is it possible using annotation set default value to Gson properties?
i want to use this default values after deSerialize/serialize
#SerializedName(key = "a", defaultValue = "hi")
public String a;
#SerializedName("b")
public String b;

You can set a default value in your setter method if the variable is null
#SerializedName("yourVariable")
public String yourVariable;
public String getYourVariable(){
if(yourVariable==null){
return defaultValue;
}
return yourVariable;
}

Related

How can I return a string in a method created by me at Android Studio?

How is possible to return a string value in a activity in Java Android Studio, to another? I am trying these 3 codes below, to get the path that I want, and to return it into a string value.
Some trys:
1)
public static String s = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+UUID.randomUUID().toString()+"audio_record.3gp";
2)
public static String retornaString(){
String s=null;
s = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+ UUID.randomUUID().toString()+"audio_record.3gp";
return s;
}
3)
public static retornar(String retorno){
retorno = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+UUID.randomUUID().toString()+"audio_record.3gp";
System.out.println(retorno);
return retorno;
}
ERRORS in 3):
Invalide method declaration; return type required
Modifier 'static' not allowed here
Cannot return a value from a method with void result type
How to fix it? Which type of method I have to use?
Thank you.
String yourStringVariable = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+UUID.randomUUID().toString()+"audio_record.3gp";
When starting Activity2 from Activity1do the following:
Intent intent = new Intent(Activity1.this,Activity2.class);
intent.putExtra("key",yourStringVariable);
startActivity(intent);
To retrieve the string when you are in Activity2
String myStringFromActivity1 = getIntent().getStringExtra("key");
You can read this article here https://medium.com/#peterekeneeze/passing-data-between-activities-2d0ef122f19d

How do you parse json object inside a json array?

I am pretty weak with JSON, and probably have a silly question, and was wondering how to parse a JSON object placed inside a JSON array.
So, as of now, I have
public Single<Profile> doProfileApiCall() {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectSingle(Profile.class);
To retrieve my profile params, but in my endpoints I have :
[{"Name": "this", "Email","that#gmail.com"}]
I have my endpoint set up as :
public static final String ENDPOINT_PROFILE =
BuildConfig.BASE_URL
+ "/linktojson";
which gives me the above JSON.
but the issue is the [], how do I modify this with :
public Single<Profile> doProfileApiCall() {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectSingle(Profile.class);
such that I can use my profile.java model class which has
public class Profile {
#Expose
#SerializedName("Name")
private String name;
#Expose
#SerializedName("Email")
private String email;
etc...
}
Any idea how to go about this?
In the doProfileApiCall() method instead of .getObjectSingle use
.getJSONArraySingle(ProfileList.class)
Now create a new class ProfileList.java with the following code.
List<Profile> profileList = new ArrayList<>();
public List<Profile> getProfileList() {
return profileList;
}
public void setProfileList(List<Profile> profileList) {
this.profileList = profileList;
}
Change the returntype of the doProfileApiCall method to
public Single<ProfileList> doProfileApiCall()
Whenever you want to access the data use it with the list position 0, when in future you get more data, you can index the data accordingly.
Generally, if JSON root object is an array you should use List on Java side. In your case you have array so use related method:
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectListSingle(Profile.class);
Rx2ANRequest source.

Retrofit SimpleXMLConverter NumberFormatException on empty attribute

I am using Retrofit and SimpleXMLConverter to get and deserialize an XML file. I am converting an attribute to type long. It would work fine if the attribute wasn´t sometimes "", aka empty.
I tried using
#Attribute(empty="-1")
for the cases this attribute should be empty, so it should return "-1" but it does not do so. Is the usage of this empty attribute correct?
It would work fine if the attribute wasn´t sometimes "", aka empty.
This is not correct here: The attributes value - seen as string - is not empty in the meaning of missing or "nothing", it's an empty string.
Here's an example:
XML:
<root value=""></root>
Java class:
#Root(name = "root")
public class Example
{
#Attribute(name = "value", empty = "-1", required = false)
private long value;
#Override
public String toString()
{
return "Example{" + "value=" + value + '}';
}
}
This throws - and that's reasonable - a NumberFormatException. If you replace the type of value with String you wont catch an exception, value is set as an empty string (""). On the other hand, keeping string type but removing the attribute in XML will set "-1" as value (that's why required = false is used). Now the Serializer can't find any value and therefore sets the default one.
You could handle this in your class internally, like let the corresponding getter-method return -1 in case of an empty string:
public long getValue()
{
if( value == null || value.isEmpty() == true )
{
return -1;
}
return Long.valueOf(value);
}
(Don't forget to change your code according this - in my example you have to change toString()-method)
But there's a better solution: Simple allows you to implement custom Transformer for any types (don't mix with Converter!). With these you can implement type -> String (write) and String -> type (read) as you need.
Based on my example above, here's an implementation:
public class LongTransformer implements Transform<Long>
{
// Default value which is set if no / empty input is available
private final long defaultValue;
public LongTransformer(long defaultValue)
{
this.defaultValue = defaultValue;
}
public LongTransformer()
{
this(-1); // Just in case you always have -1 as default
}
#Override
public Long read(String value) throws Exception
{
// If there's no or an empty String the default value is returned
if( value == null || value.isEmpty() == true )
{
return defaultValue; //
}
return Long.valueOf(value); // Return the value
}
#Override
public String write(Long value) throws Exception
{
/*
* Nothing special here. In case you you need a empty string if
* value = -1, you can do it here.
*/
return value.toString();
}
}
And finally a example how to use. The key parts are between the two lines:
final String xml = "<root value=\"\">\n"
+ "</root>";
// ---------------------------------------------------------------------
final LongTransformer numberTransformer = new LongTransformer(-1);
RegistryMatcher m = new RegistryMatcher();
m.bind(long.class, numberTransformer);
Serializer ser = new Persister(m);
// ---------------------------------------------------------------------
Example root = ser.read(Example.class, xml);
System.out.println(root);
Output:
Example{value=-1}
#vandus, here is what I did so far:
I created an adapter in the Main onCreate class, the Model that I pass in as a List is the root node of the XML file:http://www.w3schools.com//xml/simple.xml
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://www.w3schools.com")
.setConverter(new SimpleXMLConverter())
.build();
GitHubService foodService = restAdapter.create(GitHubService.class);
List<BreakfastMenu> repos = foodService.getFile();
repos.toString();
public interface GitHubService
{
#GET("/xml/simple.xml")
List<BreakfastMenu> getFile();
}

GSON does not cast Json string to class

I am trying to convert JSonObject string to some specific classes.
MyClass mc= new Gson().fromJson(jo.toString(),MyClass.class);
After this step all values of mc is null.
Value of the jo.toString() :
{
"__type":"MyClass:#MyProject.Model",
"ID":1,
"Comment":"First Record",
"SubClassID":534,
"Active":true,
"Date":"\/Date(1323087840000+0200)\/"
}
MyClass.java has attributes ID, Comment...
Thanks Regards...
MyClass.Java:
public class MyClass extends ABase
{
private String _Comment;
public String getComment(){
return _Comment;
}
public void setComment(String value){
_Comment = value;
}
private Integer _ID;
public Integer getID(){
return _ID;
}
public void setID(Integer value){
_ID = value;
}
private java.util.Date _Date;
public java.util.Date getDate(){
return _Date;
}
public void setDate(java.util.Date value){
_Date = value;
}
}
The problem is that the JSON element names do not match the Java field names, and no explicit alternative name-mapping configuration was provided to Gson.
Possible Solutions:
Change the Java field names to exactly match the JSON element names. This of course isn't always possible, e.g., when the JSON element names include characters or formats not valid for Java field names.
Change the JSON element names to exactly match the Java field names. This of course isn't always possible, e.g., when the JSON is from a third party.
Provide Gson with name-mappings, using either the #SerializedName annotation, or a FieldNamingPolicy.

ORMLite where clausule in String Array

I use ormlite and I have a db with a field:
public static final String NAME = "name";
#DatabaseField (canBeNull = false, dataType = DataType.SERIALIZABLE, columnName = NAME)
private String[] name = new String[2];
And I would like to get all elements that name[0] and name[1] are "car". I try to add a where clausule like:
NAMEDB nameDB = null;
Dao<NAMEDB, Integer> daoName = this.getHelper().getDao(NAMEDB.class);
QueryBuilder<NAMEDB, Integer> queryName = daoName.queryBuilder();
Where<NAMEDB, Integer> where = queryName.where();
where.in(nameDb.NAME, "car");
But it doesn't work because it's an array string.
I have other fields:
public static final String MARK = "mark";
#DatabaseField (canBeNull = false, foreign = true, index = true, columnName = MARK)
private String mark = null;
And I can do this:
whereArticulo.in(nameDB.MARK, "aaa");
How can I solve my problem? Thanks.
It seems to me that a third option to store a string array (String[] someStringArray[]) in the database using Ormlite would be to define a data persister class that converts the string array to a single delimited string upon storage into the database and back again to a string array after taking it out of the database.
E.g., persister class would convert ["John Doe", "Joe Smith"] to "John Doe | Joe Smith" for database storage (using whatever delimiter character makes sense for your data) and converts back the other way when taking the data out of the database.
Any thoughts on this approach versus using Serializable or a foreign collection? Anyone tried this?
I just wrote my first persister class and it was pretty easy. I haven't been able to identify through web search or StackOverflow search that anyone has tried this.
Thanks.
As ronbo4610 suggested, it is a good idea to use a custom data persister in this case, to store the array as a string in the database separated by some kind of delimiter. You can then search the string in your WHERE clause just as you would any other string. (For example, using the LIKE operator)
I have implemented such a data persister. In order to use it, you must add the following annotation above your String[] object in your persisted class:
#DatabaseField(persisterClass = ArrayPersister.class)
In addition, you must create a new class called "ArrayPersister" with the following code:
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.SqlType;
import com.j256.ormlite.field.types.StringType;
import org.apache.commons.lang3.StringUtils;
public class ArrayPersister extends StringType {
private static final String delimiter = ",";
private static final ArrayPersister singleTon = new ArrayPersister();
private ArrayPersister() {
super(SqlType.STRING, new Class<?>[]{ String[].class });
}
public static ArrayPersister getSingleton() {
return singleTon;
}
#Override
public Object javaToSqlArg(FieldType fieldType, Object javaObject) {
String[] array = (String[]) javaObject;
if (array == null) {
return null;
}
else {
return StringUtils.join(array, delimiter);
}
}
#Override
public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) {
String string = (String)sqlArg;
if (string == null) {
return null;
}
else {
return string.split(delimiter);
}
}
}
Unfortunately ORMLite does not support querying fields that are the type SERIALIZABLE. It is storing the array as a serialized byte[] so you cannot query against the values with an IN query like:
where.in(nameDb.NAME, "car");
ORMLite does support foreign collections but you have to set it up yourself with another class holding the names. See the documentation with sample code:
http://ormlite.com/docs/foreign-collection

Categories

Resources