GSON Ignore missing values from JSON string - android

I am using GSON in my android app. Currently, I am setting a method that contains a value from my JSON string called "followed". One of items in the JSON string contains followed and the second string does not. I use Realm to persist the unique object so as you can see it just gets overwritten.
Here are 2 json strings to compare as an example:
{"customer_case":"OFFICE001","circle_id":"3","address":"10 Canal St","city":"Bristol","state":"PA","zip":"19007","county":"Bucks County","apt_no":"","latitude":"40.1012666","longitude":"-74.855304","profile_picture":"uploads/thumbnails/2014/06/07/16/1402165202_3_16_539356ad9134b3.jpg","id":"539356ad9134b3","google_address":"10 Canal Street","google_city":"Bristol","google_state":"Pennsylvania","verified_zip":"19007","google_county":"Bucks County","status":"Active","add_date":"2014-06-07","circle_name":"Test Portfolio","step":"Rental","loan":"","winterized":null,"boiler":null,"sump_pump":null,"septic":null,"police_id":null,"police":null,"police_phone":null,"electric_id":null,"electric":null,"electric_phone":null,"sewer_id":null,"sewer":null,"sewer_phone":null,"water_id":null,"water":null,"water_phone":null,"fsm_company_id":"5","fsm_company":"Assero Services LLC - FSM","fsm_email":"leemertins#assero24.com","fsm_phone":"2155868317","hoa_id":null,"hoa":null,"hoa_email":null,"hoa_phone":null,"client_id":"9","client":"Test Client","client_email":"krishna162#gmail.com","client_phone":"2157830782","broker_contact_id":null,"broker":null,"broker_email":null,"broker_phone":null,"lawn_contractor":null,"cleaning_contractor":null,"bedroom":null,"bathroom":null,"sqft":null,"lot_size":null,"list_price":"538525","built":null,"assign_date":"06/07/2014","lock_box":null,"gate_code":null,"key_code":null,"property_type":"Unknown","description":null,"sub_status":null,"occupancy_status":null,"street_view":"uploads/2015/06/25/4036/0470e4cd-ce9d-4439-8031-6be5101cd09c.JPG","marketing_front":"uploads/2015/06/25/4036/b099a190-f354-454a-8479-bec67bc41988.JPG","followed":"1"}
{"customer_case":"OFFICE001","circle_id":"3","address":"10 Canal St","city":"Bristol","state":"PA","zip":"19007","county":"Bucks County","apt_no":"","latitude":"40.1012666","longitude":"-74.855304","profile_picture":"uploads/thumbnails/2014/06/07/16/1402165202_3_16_539356ad9134b3.jpg","id":"539356ad9134b3","google_address":"10 Canal Street","google_city":"Bristol","google_state":"Pennsylvania","verified_zip":"19007","google_county":"Bucks County","status":"Active","add_date":"2014-06-07","circle_name":"Test Portfolio","step":"Rental","loan":"","winterized":null,"boiler":null,"sump_pump":null,"septic":null,"police_id":null,"police":null,"police_phone":null,"electric_id":null,"electric":null,"electric_phone":null,"sewer_id":null,"sewer":null,"sewer_phone":null,"water_id":null,"water":null,"water_phone":null,"fsm_company_id":"5","fsm_company":"Assero Services LLC - FSM","fsm_email":"leemertins#assero24.com","fsm_phone":"2155868317","hoa_id":null,"hoa":null,"hoa_email":null,"hoa_phone":null,"client_id":"9","client":"Test Client","client_email":"krishna162#gmail.com","client_phone":"2157830782","broker_contact_id":null,"broker":null,"broker_email":null,"broker_phone":null,"lawn_contractor":null,"cleaning_contractor":null,"bedroom":null,"bathroom":null,"sqft":null,"lot_size":null,"list_price":"538525","built":null,"assign_date":"06/07/2014","lock_box":null,"gate_code":null,"key_code":null,"property_type":"Unknown","description":null,"sub_status":null,"occupancy_status":null,"street_view":"uploads/2015/06/25/4036/0470e4cd-ce9d-4439-8031-6be5101cd09c.JPG","marketing_front":"uploads/2015/06/25/4036/b099a190-f354-454a-8479-bec67bc41988.JPG"}
Note the difference is the followed item at the end of the json string.
From the GSON documentation it says:
"While deserialization, a missing entry in JSON results in setting the corresponding field in the object to null."
Is there a way to override this and not automatically set it to null, instead just skip the field?
Here is some code that I am using to deserialize my json:
PropertyObject prop = visnetawrap.gsonClient.fromJson(properties.get(i).toString(), PropertyObject.class);
visnetawrap.gsonClient = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
#Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class) || f.getDeclaredClass().equals(Drawable.class);
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
})
.registerTypeAdapter(Date.class, new GsonDateDeserializer())
.registerTypeAdapter(Double.class, new TypeAdapter<Double>() {
#Override
public void write(JsonWriter out, Double value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.value(value);
}
#Override
public Double read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
String stringValue = in.nextString();
try {
return Double.valueOf(stringValue);
} catch (NumberFormatException e) {
return null;
}
}
})
.create();

Here is what I am doing as a work around:
.registerTypeAdapter(PropertyObject.class, new JsonDeserializer<PropertyObject>() {
#Override
public PropertyObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
PropertyObject prop = new PropertyObject();
JsonObject propObj = json.getAsJsonObject();
if (propObj.get("id") == null) {
return null;
}
prop.setPropertyId(propObj.get("id").getAsString());
if (propObj.get("followed") == null) {
Realm realmThread = Realm.getDefaultInstance();
PropertyObject existingProp = realmThread.where(PropertyObject.class).equalTo("propertyId", propObj.get("id").getAsString()).findFirst();
if (existingProp == null) {
prop.setPropertyFollowed(0);
}
else {
prop.setPropertyFollowed(existingProp.getPropertyFollowed());
}
realmThread.close();
}
else {
prop.setPropertyFollowed(propObj.get("followed").getAsInt());
}
return prop;
}
})

you may create your own TypeAdapter
public class YourTypeAdapter extends TypeAdapter<PropertyObject> {
#Override
public PropertyObject read(final JsonReader in) throws IOException {
final PropertyObject obj = new PropertyObject(); //I don't know how is your obj
in.beginObject();
boolean hasFollowedField = false;
while (in.hasNext()) {
switch (in.nextName()) {
case "gate_code":
//set value to your obj
obj.setValue(in.nextString())
break;
//do same thing to others...
//...
case "followed":
hasFollowedField = true;
//set value to obj
break;
}
if (!hasFollowedField) {
//set followed value to obj what you want
}
}
in.endObject();
return obj;
}
#Override
public void write(final JsonWriter out, final PropertyObject obj) throws IOException {
out.beginObject();
out.name("gate_code").value(gate_code.getGateCode());
//simple set name and value from obj to JsonWriter
out.endObject();
}
}
and then register the TypeAdapter to your GsonBuilder obj
hope it would help

Related

finding in an array if specific fileds exists or not

This is my api
{}JSON
[]products
{}0
product-name : "Fiting"
product-id : "1"
product-description : "Door"
product-image : "https://image/logo.jpg"
product-categoryid : "2"
category-name : "Furniture"
{}1
product-name : "Bathroom"
product-id : "2"
product-description : "Services"
product-image : "https://image/logo.jpg"
product-categoryid : "1"
category-name : "Plumber"
subcategory-id : "1"
subcategory-name : "Bathroom"
subCategoryDetailModelClass.setSubCategoryId(productObject.getInt("subcategory-id"));
subCategoryDetailModelClass.setSubCategoryName(productObject.getString("subcategory-name"));
i cannot add subcategory-id,subcategory-name in my arraylist since it is not available at 0th position.....so how to check condition that if in api subcategory-id,subcategory-name is not available add other items in the list
StringRequest stringRequest = new StringRequest(Request.Method.GET,URLs.productURL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("zsded", response.toString());
try {
JSONObject obj = new JSONObject(response);
JSONArray productArray = obj.getJSONArray("products");
//now looping through all the elements of the json array
for (int i = 0; i < productArray.length(); i++) {
JSONObject productObject = productArray.getJSONObject(i);
SubCategoryDetailModelClass subCategoryDetailModelClass = new SubCategoryDetailModelClass();
// if(productObject.getInt("subcategory-id"))
subCategoryDetailModelClass.setProduct_name(productObject.getString("product-name"));
subCategoryDetailModelClass.setProduct_id(productObject.getInt("product-id"));
subCategoryDetailModelClass.setProduct_desc(productObject.getString("product-description"));
subCategoryDetailModelClass.setProduct_imgURL(productObject.getString("product-image"));
subCategoryDetailModelClass.setProduct_CategoryId(productObject.getInt("product-categoryid"));
subCategoryDetailModelClass.setProduct_Category_Name(productObject.getString("category-name"));
subCategoryDetailModelClass.setSubCategoryId(productObject.getInt("subcategory-id"));
subCategoryDetailModelClass.setSubCategoryName(productObject.getString("subcategory-name"));
subCategoryListDetailModelClassArray.add(subCategoryDetailModelClass);
Log.d("subcatdetail", String.valueOf(subCategoryDetailModelClass));
}
Use this class
public class JSONHelper {
public static String getString(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
return json.getString(tag);
}
return "";
}
public static int getInt(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
if(json.get(tag) instanceof String) {
if(json.getString(tag).equalsIgnoreCase("None")) {
return -1;
}
if(!json.getString(tag).equals("")) {
return Integer.parseInt(json.getString(tag));
} else {
return -1;
}
}
return json.getInt(tag);
}
return -1;
}
public static boolean getBoolean(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
Object value = json.get(tag);
if(value instanceof String) {
return PrimitiveHelper.StringToBoolean((String) value);
} else if (value instanceof Integer) {
return PrimitiveHelper.IntegerToBoolean((int)value);
}
return json.getBoolean(tag);
}
return false;
}
public static Boolean getBooleanBoxed(JSONObject json, String tag) throws JSONException {
if(mJSONValueAvailable(json, tag)) {
Object value = json.get(tag);
if(value instanceof String) {
return PrimitiveHelper.StringToBooleanBoxed((String) value);
} else if (value instanceof Integer) {
return PrimitiveHelper.IntegerToBooleanBoxed((int) value);
}
return json.getBoolean(tag);
}
return null;//false;
}
private static boolean mJSONValueAvailable(JSONObject json, String tag) {
return json.has(tag) && !json.isNull(tag);
}
// private static Boolean mJSONValueAvailableBoxed(JSONObject json, String tag) {
// return json.has(tag) && !json.isNull(tag);//
// }
public static JSONArray sortJsonArray(JSONArray array, String sort) {
final String sortKey = sort;
//Logger.d("sortJSONArray by::: " + sortKey);
List<JSONObject> jsons = new ArrayList<JSONObject>();
try {
for (int i = 0; i < array.length(); i++) {
jsons.add(array.getJSONObject(i));
}
Collections.sort(jsons, new Comparator<JSONObject>() {
#Override
public int compare(JSONObject lhs, JSONObject rhs) {
try {
String lid = lhs.getString(sortKey);
String rid = rhs.getString(sortKey);
// Here you could parse string id to integer and then compare.
return lid.compareTo(rid);
} catch (JSONException e) {
e.printStackTrace();
}
return 0;
}
});
} catch (JSONException e) {
e.printStackTrace();
}
return new JSONArray(jsons);
}
}
Call this as follows
subCategoryDetailModelClass.setProduct_name(JSONHelper.getString(productObject, "product-name"));
subCategoryDetailModelClass.setProduct_id(JSONHelper.getInt(productObject,"product-id"));
subCategoryDetailModelClass.setProduct_desc(JSONHelper.getString(productObject, "product-description"));
subCategoryDetailModelClass.setProduct_imgURL(JSONHelper.getString(productObject, "product-image"));
subCategoryDetailModelClass.setProduct_CategoryId(JSONHelper.getInt(productObject,"product-categoryid"));
subCategoryDetailModelClass.setProduct_Category_Name(JSONHelper.getString(productObject, "category-name"));
subCategoryDetailModelClass.setSubCategoryId(JSONHelper.getInt(productObject, "subcategory-id"));
subCategoryDetailModelClass.setSubCategoryName(JSONHelper.getString(productObject,"subcategory-name"));
subCategoryListDetailModelClassArray.add(subCategoryDetailModelClass);
Use Opt methods, For e.g.
optInt(String name, int fallback)
Returns the value mapped by name if it exists and is an int or can be
coerced to an int, or fallback otherwise.
There are optMethods for mostly primitive datatypes, check here

How do I write a json field to retrieve this?

I am currently using json for my code to retrieve an array of boolean values. However, i am adding a subfield to achieve another array within, but I am not good with json and kind of stuck how to go about it.
Here's my code so far:
field values :
public enum Field {
/**
* Runtime Config Fields
**/
FIELD_CAN_CHANGE_PASSWORD("canChangePassword", true, canUpdate),
FIELD_MAX_AUTO_DOWNLOAD_SIZE("maxAutoDownloadSize", 5000000L),
FIELD_ALWAYS_REAUTHENTICATE("alwaysReauthenticate", false, canUpdate),
FIELD_CAN_START_CALL("canStartCall", false),
FIELD_ROOMS_ENABLED("roomsEnabled", !Core.isMessenger()),
FIELD_CAN_CREATE_ROOM("canCreateRoom", !Core.isMessenger(), canUpdate),
FIELD_MAX_ENVELOPE_TTL("maxTTL", Core.isMessenger() ? 518400L : 31536000L, canUpdate),
FIELD_MAX_BURN_ON_READ_TTL("maxBOR", 0L, canUpdate),
FIELD_MAX_UPLOAD_SIZE("maxUploadSize", -1L, true),
FIELD_FRIEND_FINDER("friendFinder", !Core.isEnterprise(), canUpdate),
FIELD_ONLY_SHOW_IN_NETWORK_CONTACTS("onlyShowInNetwork", false),
FIELD_CAN_ADD_CONTACT("canAddContact", true, canUpdate),
FIELD_FORCE_DEVICE_LOCKOUT("forceDeviceLockout", 5L, canUpdate),
FIELD_VERIFICATION_MODE("verificationMode", VerificationMode.OPTIONAL.getValue(), true),
FIELD_ENABLE_NOTIFICATION_PREVIEW("enableNotificationPreview", true, true),
FIELD_DIRECTORY_ENABLED("directoryEnabled", true, true);
public String fieldName;
public Object defaultValue;
public boolean updateFromServer;
Field(String key, Object defaultValue) {
this(key, defaultValue, true);
}
Field(String key, Object defaultValue, boolean updateFromServer) {
this.fieldName = key;
this.defaultValue = defaultValue;
this.updateFromServer = updateFromServer;
}
}
putting values in field:
private void putValueForField(JSONObject configuration, Field field) {
try {
if (configuration.isNull(field.fieldName)) {
Object value = field.defaultValue;
if (value instanceof long[]) {
JSONArray array = new JSONArray();
for (long obj : (long[]) field.defaultValue) {
array.put(obj);
}
value = array;
}
runtimeConfiguration.put(field.fieldName, value);
} else {
runtimeConfiguration.put(field.fieldName, configuration.get(field.fieldName));
}
} catch (JSONException e) {
}
}
getting values :
private Object getValueForField(Field field) {
if (runtimeConfiguration.has(field.fieldName) && field.updateFromServer) {
try {
Object value = runtimeConfiguration.get(field.fieldName);
if (value instanceof JSONArray) {
JSONArray values = (JSONArray) value;
if (values.get(0) instanceof Number) {
long[] retVals = new long[values.length()];
for (int i = 0; i < values.length(); i++) {
retVals[i] = ((Number) values.get(i)).longValue();
}
return retVals;
}
} else if (value instanceof Number) {
return ((Number) value).longValue();
} else {
return value;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return field.defaultValue;
}
one of the methods using the fields above:
public boolean canChangePassword() {
return (boolean) getValueForField(Field.FIELD_CAN_CHANGE_PASSWORD);
}
My new json is :
{"enableNotificationPreview":true,"destructOnRead":[30,60,300],"alwaysReauthenticate":false,"forceDeviceLockout":0,"permmod":1516894585,"maxBOR":0,"roomsEnabled":true,"directoryEnabled":true,"canStartCall":true,"canAddContact":true,"legacyDownload":false,"verificationMode":1,"restrictedAdmin":false,"canChangePassword":true,"friendFinder":true,"NEWVALUE":{"canStartNewValue1":true,"canStartroupValue":true,"canVideoCall":true,"canStartRoomValue":true,"canAddtoValue":true,"canStartValueshare":true},"canCreateRoom":true,"maxTTL":2592000,"onlyShowInNetwork":false,"maxUploadSize":null,"availableEnvelopeTTL":[0,600,3600,86400,604800,2592000],"maxAutoDownloadSize":7340032}
where I am plugging in :
"NEWVALUE":{"canStartNewValue1":true,"canStartroupValue":true,"canVideoCall":true,"canStartRoomValue":true,"canAddtoValue":true,"canStartValueshare":true}
Not sure how to update my putValueForField to reflect this new json and the corresponding fields. Any idea?
To check and retrieve JSONObject from the json object you can modify your method to check for instance of JSONObject and assign value to it.
private void putValueForField(JSONObject configuration, Field field) {
try {
if (configuration.isNull(field.fieldName)) {
Object value = field.defaultValue;
if (value instanceof long[]) {
JSONArray array = new JSONArray();
for (long obj : (long[]) field.defaultValue) {
array.put(obj);
}
value = array;
}
// this is how you check if fieldName is of type jsonobject
if (value instanceof JSONObject) {
JSONObject valueObject = configuration.getJSONObject(field.fieldName);
value = valueObject;
}
runtimeConfiguration.put(field.fieldName, value);
} else {
runtimeConfiguration.put(field.fieldName, configuration.get(field.fieldName));
}
} catch (JSONException e) {
}
}
Form what I can understand you are just getting the values from JSON and saving it in field in that case:
I think in this method ultimately you are just storing all values as object only so while retrieving you have to do all this check again.
If you are getting the response from server with fixed Object fields and object values you should be creating a class from that configuration where you will know what exactly it will return. That would really make life easier.
Or maybe if you just need the configuration to get/update or put values you can maintain it in json object itself Android JSON doc reference
For example lets say you have this jsonobject itself, I have added the working example below, hope this helps.
import org.json.*;
class Main {
public static void main(String[] args) throws JSONException {
String jsn = "{\"enableNotificationPreview\":true,\"destructOnRead\":[30,60,300],\"" +
"alwaysReauthenticate\":false,\"forceDeviceLockout\":0,\"NEWVALUE\":{\"canStartNewValue1\":true," +
"\"canStartroupValue\":true,\"canVideoCall\":true,\"canStartRoomValue\":true},\"canCreateRoom\":true," +
"\"maxTTL\":2592000,\"onlyShowInNetwork\":false,\"maxUploadSize\":null,\"availableEnvelopeTTL\"" +
":[0,600,3600,86400,604800,2592000],\"maxAutoDownloadSize\":7340032}";
JSONObject jsnObj = new JSONObject(jsn);
Object enableNotificationPreview = jsnObj.get("enableNotificationPreview");
// or if you know it will be boolean
boolean enableNotificationPreviewBool = jsnObj.getBoolean("enableNotificationPreview");
System.out.println(enableNotificationPreview);
// output : true
System.out.println(enableNotificationPreviewBool);
// output : true
JSONObject NEWVALUEObj = jsnObj.getJSONObject("NEWVALUE");
// now again you can extract values from it
boolean canStartNewValue1 = NEWVALUEObj.getBoolean("canStartNewValue1");
System.out.println(canStartNewValue1);
NEWVALUEObj.put("canStartNewValue1", false);
System.out.println(NEWVALUEObj.toString());
jsnObj.put("forceDeviceLockout", 23456);
// now canStartNewValue1 value is changed to false in the object
// and forceDeviceLockout is also 23456
System.out.println(jsnObj.toString());
}
}

How to iterate JsonReader twice?

I am facing the following problem: I have json like this
{
"type": "objectType",
"body": {
//could be one of five different object types
}
}
"body" could be one of fixed set of types so I am trying to implement custom TypeAdapter:
#Override
public MyObject read(final JsonReader pJsonReader) throws IOException {
if (pJsonReader.peek() == JsonToken.NULL) {
pJsonReader.nextNull();
return null;
}
pJsonReader.beginObject();
String type = null;
while (pJsonReader.hasNext()) {
final String fieldName = pJsonReader.nextString();
if (pJsonReader.peek() == JsonToken.NULL) {
pJsonReader.nextNull();
continue;
}
switch (fieldName) {
case TYPE: {
tyoe = mStringTypeAdapter.read(pJsonReader);
break;
}
case BODY: {
body = //I need to choose a particular TypeAdapter basing on type field
}
default: {
pJsonReader.skipValue();
}
}
}
pJsonReader.endObject();
return MyObject(type, body);
}
The problem is that I need to choose TypeAdapter for "body" basing on "type" so I need to copy somehow JsonReader steam and iterate it once more time when I find "type"value.
Any idea how I can do that?
If you are controlling the structure of the JSON, then it would be good to nest the body so you are always able to read the type first.
However, if you cannot change the structure of the JSON you could create an in-memory representation using JsonParser and then have the respective adapter for type read from that:
public class MyObjectTypeAdapter extends TypeAdapter<MyObject> {
#Override
public void write(JsonWriter out, MyObject value) throws IOException {
// You will have to implement this in case you are
// also writing JSON data
throw new UnsupportedOperationException();
}
#Override
public MyObject read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
String type = null;
JsonElement body = null;
in.beginObject();
while (in.hasNext()) {
String fieldName = in.nextString();
if (in.peek() == JsonToken.NULL) {
in.nextNull();
continue;
}
switch (fieldName) {
case "TYPE": {
type = in.nextString();
break;
}
case "BODY": {
body = JsonParser.parseReader(in);
break;
}
default: {
in.skipValue();
}
}
}
in.endObject();
// Get the corresponding adapter for `type`
// Possibly also have to create this MyObjectTypeAdapter using a
// TypeAdapterFactory to be able to use Gson for the adapter lookup
TypeAdapter<?> bodyAdapter = ...
return new MyObject(type, bodyAdapter.fromJsonTree(body));
}
}
This won't be that efficient, but should not be a big issue if the body is not that complex.

Error while trying to cache a HashSet using Android Room Library

I'm willing to try the new Room Library from Android and I met the below error:
Error:(19, 29) error: Cannot figure out how to save this field into
database. You can consider adding a type converter for it.
This error refers to the following class member:
private HashSet<String> fruits;
I have the following class:
#Entity(tableName = "SchoolLunches")
public class SchoolLunch {
#PrimaryKey(autoGenerate = true)
private int lunchId;
private boolean isFresh;
private boolean containsMeat;
private HashSet<String> fruits;
public int getLunchId() {
return lunchId;
}
public void setLunchId(int lunchId) {
this.lunchId = lunchId;
}
public boolean isFresh() {
return isFresh;
}
public void setFresh(boolean fresh) {
isFresh = fresh;
}
public boolean isContainsMeat() {
return containsMeat;
}
public void setContainsMeat(boolean containsMeat) {
this.containsMeat = containsMeat;
}
public HashSet<String> getFruits() {
return fruits;
}
public void setFruits(HashSet<String> fruits) {
this.fruits = fruits;
}
Also, there is a relative DAO class:
#Dao
public interface SchoolLunchDAO {
#Query("SELECT * FROM SchoolLunches")
List<SchoolLunch> getAll();
#Insert
void insertAll(SchoolLunch... schoolLunches);
#Query("DELETE FROM SchoolLunches")
void deleteAll();
}
Since I'm trying to be a very good developer, I wrote a unit test as follows:
#Test
public void singleEntityTest() {
HashSet<String> fruitSet = new HashSet<>();
fruitSet.add("Apple");
fruitSet.add("Orange");
SchoolLunch schoolLunch = new SchoolLunch();
schoolLunch.setContainsMeat(false);
schoolLunch.setFresh(true);
schoolLunch.setFruits(fruitSet);
schoolLunchDAO.insertAll(schoolLunch);
List<SchoolLunch> schoolLunches = schoolLunchDAO.getAll();
assertEquals(schoolLunches.size(), 1);
SchoolLunch extractedSchoolLunch = schoolLunches.get(0);
assertEquals(false, extractedSchoolLunch.isContainsMeat());
assertEquals(true, extractedSchoolLunch.isFresh());
assertEquals(2, extractedSchoolLunch.getFruits().size());
}
What should I do here?
What should I do here?
You could create a type converter, as suggested by the error message. Room does not know how to persist a HashSet<String>, or a Restaurant, or other arbitrary objects.
Step #1: Decide what basic type you want to convert your HashSet<String> into (e.g., a String)
Step #2: Write a class with public static type conversion methods, annotated with #TypeConverter, to do the conversion (e.g., HashSet<String> to String, String to HashSet<String>), in some safe fashion (e.g., use Gson, formatting your String as JSON)
Step #3: Add a #TypeConverters annotation to your RoomDatabase or other scope, to teach Room about your #TypeConverter methods
For example, here are a pair of type converter methods for converting a Set<String> to/from a regular String, using JSON as the format of the String.
#TypeConverter
public static String fromStringSet(Set<String> strings) {
if (strings==null) {
return(null);
}
StringWriter result=new StringWriter();
JsonWriter json=new JsonWriter(result);
try {
json.beginArray();
for (String s : strings) {
json.value(s);
}
json.endArray();
json.close();
}
catch (IOException e) {
Log.e(TAG, "Exception creating JSON", e);
}
return(result.toString());
}
#TypeConverter
public static Set<String> toStringSet(String strings) {
if (strings==null) {
return(null);
}
StringReader reader=new StringReader(strings);
JsonReader json=new JsonReader(reader);
HashSet<String> result=new HashSet<>();
try {
json.beginArray();
while (json.hasNext()) {
result.add(json.nextString());
}
json.endArray();
}
catch (IOException e) {
Log.e(TAG, "Exception parsing JSON", e);
}
return(result);
}
I created the following class and now it works. Thank you, CommonsWare!
public class Converters {
private static final String SEPARATOR = ",";
#TypeConverter
public static HashSet<String> fromString(String valueAsString) {
HashSet<String> hashSet = new HashSet<>();
if (valueAsString != null && !valueAsString.isEmpty()) {
String[] values = valueAsString.split(SEPARATOR);
hashSet.addAll(Arrays.asList(values));
}
return hashSet;
}
#TypeConverter
public static String hashSetToString(HashSet<String> hashSet) {
StringBuilder stringBuilder = new StringBuilder();
for (String currentElement : hashSet) {
stringBuilder.append(currentElement);
stringBuilder.append(SEPARATOR);
}
return stringBuilder.toString();
}
}

Check if Parse Array contain value android

I use Parse in android. I am trying to check if an array contain an value (ObjectId).
private void getCurrentObject() {
query = ParseQuery.getQuery("Group");
query.getInBackground(objectid, new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
object = all;
if (e == null) {
if (userexists(object.getJSONArray("members_array"), currentUser.getObjectId())) {
Toast.makeText(GroupActivity.this, "isDo", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(GroupActivity.this, "isNot", Toast.LENGTH_SHORT).show();
}
}
}
});
}
private boolean userexists(JSONArray jsonArray, String usernameToFind) {
return jsonArray.toString().contains(usernameToFind);
}
While run the app i got this error
"java.lang.NullPointerException: Attempt to invoke virtual method
'org.json.JSONArray
com.parse.ParseObject.getJSONArray(java.lang.String)' on a null object
reference
Remove this line
object = all;
Or, you probably meant all = object
Then, you need to loop over the JSONArray, not toString it.
private boolean userexists(JSONArray jsonArray, String usernameToFind) {
if (jsonArray == null) return false;
for (int i = 0; i < jsonArray.length(); i++) {
String s = jsonArray.optString(i, "");
if (s.equals(usernameToFind)) return true;
}
return false;
}
Using this method
String optString(int index, String fallback)
Returns the value at
index if it exists, coercing it if necessary.

Categories

Resources