Getting started with AndroidLayoutsGradle for AndroidRecyclerView onClickListenersNavigationViewIntentJSON in Android with org.jsonAndroid StudioResourcesData Binding LibraryExceptionsGetting Calculated View DimensionsAsyncTaskSharedPreferencesEmulatorMaterial DesignLint WarningsServiceStoring Files in Internal & External StorageWebViewProject SDK versionsRecyclerViewGoogle Maps API v2 for AndroidPorterDuff Mode9-Patch ImagesAndroid NDKRecyclerView DecorationsCamera 2 APIViewPagerCardViewHttpURLConnectionSQLiteADB (Android Debug Bridge)ButterKnifeSupporting Screens With Different Resolutions, SizesGlideRetrofit2DialogACRAGreenDAOFormatting StringsNotificationsAlarmManagerFragmentsHandlerCreating Custom ViewsBroadcastReceiverActivitySnackbarRuntime Permissions in API-23 +Logging and using LogcatVectorDrawable and AnimatedVectorDrawableTools AttributesToastInterfacesAnimatorsLocationTheme, Style, AttributeThe Manifest FileParcelableMediaPlayerMultidex and the Dex Method LimitData Synchronization with Sync AdapterMenuInstant Run in Android StudioPicassoBluetooth and Bluetooth LE APIRoboGuiceMemory LeaksUniversal Image LoaderVolleyWidgetsDate and Time PickersIntegrate Google Sign InIn-app BillingFloatingActionButtonContentProviderDagger 2RealmUnit testing in Android with JUnitAndroid VersionsWi-Fi ConnectionsSensorManagerLocalization with resources in AndroidProgressBarCustom FontsVibrationGoogle Awareness APIsText to Speech(TTS)UI LifecycleSpinnerData Encryption/DecryptionTesting UI with EspressoWriting UI tests - AndroidGreenRobot EventBusOkHttpEnhancing Android Performance Using Icon FontsHandling Deep LinksCanvas drawing using SurfaceViewFirebaseCrash Reporting ToolsCheck Internet ConnectivityFacebook SDK for AndroidUnzip File in AndroidAndroid Places APICreating your own libraries for Android applicationsGsonDevice Display MetricsTextViewListViewBuilding Backwards Compatible AppsLoaderProGuard - Obfuscating and Shrinking your codeDetect Shake Event in AndroidTypedef Annotations: @IntDef, @StringDefCapturing ScreenshotsMVP ArchitectureOrientation ChangesXposedSecurityPackageManagerImageViewGesture DetectionDoze ModeAndroid Sound and MediaSearchViewCamera and GalleryCallback URLTwitter APIsDrawablesColorsConstraintLayoutRenderScriptFrescoSwipe to RefreshAutoCompleteTextViewInstalling apps with ADBIntentServiceAdMobImplicit IntentsPublish to Play StoreFirebase Realtime DataBaseImage CompressionEmail ValidationKeyboardButtonTextInputLayoutBottom SheetsCoordinatorLayout and BehaviorsEditTextAndroid Paypal Gateway IntegrationFirebase App IndexingFirebase Crash ReportingDisplaying Google AdsAndroid Vk SdkLocalized Date/Time in AndroidCount Down TimerBarcode and QR code readingOtto Event BusTransitionDrawablePort Mapping using Cling library in AndroidCreating Overlay (always-on-top) WindowsExoPlayerInter-app UI testing with UIAutomatorMediaSessionSpeech to Text ConversionFileProviderPublish .aar file to Apache Archiva with GradleXMPP register login and chat simple exampleAndroid AuthenticatorRecyclerView and LayoutManagersAudioManagerJob SchedulingAccounts and AccountManagerIntegrate OpenCV into Android StudioSplit Screen / Multi-Screen ActivitiesThreadMediaStoreTime UtilsTouch EventsFingerprint API in androidMVVM (Architecture)BottomNavigationViewORMLite in androidYoutube-APITabLayoutRetrofit2 with RxJavaDayNight Theme (AppCompat v23.2 / API 14+)ShortcutManagerLruCacheJenkins CI setup for Android ProjectsZip file in androidVector DrawablesfastlaneDefine step value (increment) for custom RangeSeekBarGetting started with OpenGL ES 2.0+Check Data ConnectionAndroid Java Native Interface (JNI)FileIO with AndroidPerformance OptimizationRobolectricMoshiStrict Mode Policy : A tool to catch the bug in the Compile Time.Internationalization and localization (I18N and L10N)Fast way to setup Retrolambda on an android project.How to use SparseArrayFirebase Cloud MessagingShared Element TransitionsAndroid ThingsVideoViewViewFlipperLibrary Dagger 2: Dependency Injection in ApplicationsFormatting phone numbers with pattern.How to store passwords securelyAndroid Kernel OptimizationPaintAudioTrackWhat is ProGuard? What is use in Android?Create Android Custom ROMsJava on AndroidPagination in RecyclerViewGenymotion for androidHandling touch and motion eventsCreating Splash screenConstraintSetCleverTapPublish a library to Maven Repositoriesadb shellPing ICMPAIDLAndroid programming with KotlinAutosizing TextViewsSign your Android App for ReleaseContextActivity RecognitionSecure SharedPreferencesSecure SharedPreferencesBitmap CacheAndroid-x86 in VirtualBoxJCodecDesign PatternsOkioGoogle signin integration on androidTensorFlowAndroid game developmentNotification Channel Android OBluetooth Low EnergyLeakcanaryAdding a FuseView to an Android ProjectAccessing SQLite databases using the ContentValues classEnhancing Alert DialogsHardware Button Events/Intents (PTT, LWP, etc.)SpannableStringLooperOptimized VideoViewGoogle Drive APIAnimated AlertDialog BoxAnnotation ProcessorSyncAdapter with periodically do sync of dataCreate Singleton Class for Toast MessageFastjsonAndroid Architecture ComponentsJacksonGoogle Play StoreLoading Bitmaps EffectivelyGetting system font names and using the fontsSmartcardConvert vietnamese string to english string Android

Gson

Other topics

Parsing JSON with Gson

The example shows parsing a JSON object using the Gson library from Google.

Parsing objects:

class Robot {
    //OPTIONAL - this annotation allows for the key to be different from the field name, and can be omitted if key and field name are same . Also this is good coding practice as it decouple your variable names with server keys name 
    @SerializedName("version") 
    private String version;

    @SerializedName("age")
    private int age;
    
    @SerializedName("robotName")
    private String name;
    
    // optional : Benefit it allows to set default values and retain them, even if key is missing from Json response. Not required for primitive data types. 

    public Robot{
       version = "";
       name = "";
    }


}

Then where parsing needs to occur, use the following:

String robotJson = "{
                        \"version\": \"JellyBean\",
                        \"age\": 3,
                        \"robotName\": \"Droid\"
                   }";

Gson gson = new Gson();
Robot robot = gson.fromJson(robotJson, Robot.class);

Parsing a list:

When retrieving a list of JSON objects, often you will want to parse them and convert them into Java objects.

The JSON string that we will try to convert is the following:

{
  "owned_dogs": [
    {
      "name": "Ron",
      "age": 12,
      "breed": "terrier"
    },
    {
      "name": "Bob",
      "age": 4,
      "breed": "bulldog"
    },
    {
      "name": "Johny",
      "age": 3,
      "breed": "golden retriever"
    }
  ]
}

This particular JSON array contains three objects. In our Java code we'll want to map these objects to Dog objects. A Dog object would look like this:

private class Dog {
    public String name;
    public int age;

    @SerializedName("breed")
    public String breedName;
}

To convert the JSON array to a Dog[]:

Dog[] arrayOfDogs = gson.fromJson(jsonArrayString, Dog[].class);

Converting a Dog[] to a JSON string:

String jsonArray = gson.toJson(arrayOfDogs, Dog[].class);

To convert the JSON array to an ArrayList<Dog> we can do the following:

Type typeListOfDogs = new TypeToken<List<Dog>>(){}.getType();
List<Dog> listOfDogs = gson.fromJson(jsonArrayString, typeListOfDogs);

The Type object typeListOfDogs defines what a list of Dog objects would look like. GSON can use this type object to map the JSON array to the right values.

Alternatively, converting a List<Dog> to a JSON array can be done in a similar manner.

String jsonArray = gson.toJson(listOfDogs, typeListOfDogs);

Parsing JSON property to enum with Gson

If you want to parse a String to enum with Gson:

{"status" : "open"}

public enum Status {
    @SerializedName("open")
    OPEN,
    @SerializedName("waiting")
    WAITING,
    @SerializedName("confirm")
    CONFIRM,
    @SerializedName("ready")
    READY
}

Parsing a List<String> with Gson

Method 1

Gson gson = new Gson();
String json = "[ \"Adam\", \"John\", \"Mary\" ]";

Type type = new TypeToken<List<String>>(){}.getType();
List<String> members = gson.fromJson(json, type);
Log.v("Members", members.toString());

This is useful for most generic container classes, since you can't get the class of a parameterized type (ie: you can't call List<String>.class).

Method 2

public class StringList extends ArrayList<String> { }

...

List<String> members = gson.fromJson(json, StringList.class);

Alternatively, you can always subclass the type you want, and then pass in that class. However this isn't always best practice, since it will return to you an object of type StringList;

JSON Serialization/Deserialization with AutoValue and Gson

Import in your gradle root file

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

Import in your gradle app file

apt 'com.google.auto.value:auto-value:1.2'  
apt 'com.ryanharter.auto.value:auto-value-gson:0.3.1'  
provided 'com.jakewharton.auto.value:auto-value-annotations:1.2-update1'  
provided 'org.glassfish:javax.annotation:10.0-b28'

Create object with autovalue:

@AutoValue public abstract class SignIn {    
    @SerializedName("signin_token") public abstract String signinToken();
    public abstract String username();

    public static TypeAdapter<SignIn> typeAdapter(Gson gson) {
        return new AutoValue_SignIn.GsonTypeAdapter(gson);
    }

    public static SignIn create(String signin, String username) {
        return new AutoValue_SignIn(signin, username);
    }
}

Create your Gson converter with your GsonBuilder

Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(
                    new AutoValueGsonTypeAdapterFactory())
                .create());

Deserialize

String myJsonData = "{
    \"signin_token\": \"mySigninToken\",
    \"username\": \"myUsername\" }";
SignIn signInData = gson.fromJson(myJsonData, Signin.class);

Serialize

Signin myData = SignIn.create("myTokenData", "myUsername");
String myJsonData = gson.toJson(myData);

Using Gson is a great way to simplify Serialization and Deserialization code by using POJO objects. The side effect is that reflection is costly performance wise. That's why using AutoValue-Gson to generate CustomTypeAdapter will avoid this reflection cost while staying very simple to update when an api change is happening.

Parsing JSON to Generic Class Object with Gson

Suppose we have a JSON string:

["first","second","third"]

We can parse this JSON string into a String array :

Gson gson = new Gson();
String jsonArray = "[\"first\",\"second\",\"third\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);

But if we want parse it into a List<String> object, we must use TypeToken.

Here is the sample :

Gson gson = new Gson();
String jsonArray = "[\"first\",\"second\",\"third\"]";
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());

Suppose we have two classes below:

public class Outer<T> {
    public int index;
    public T data;
}

public class Person {
    public String firstName;
    public String lastName;
}

and we have a JSON string that should be parsed to a Outer<Person> object.

This example shows how to parse this JSON string to the related generic class object:

String json = "......";
Type userType = new TypeToken<Outer<Person>>(){}.getType();
Result<User> userResult = gson.fromJson(json,userType);

If the JSON string should be parsed to a Outer<List<Person>> object :

Type userListType = new TypeToken<Outer<List<Person>>>(){}.getType();
Result<List<User>> userListResult = gson.fromJson(json,userListType); 

Adding Gson to your project

dependencies {
    compile 'com.google.code.gson:gson:2.8.1'
}

To use latest version of Gson

The below line will compile latest version of gson library everytime you compile, you do not have to change version.

Pros: You can use latest features, speed and less bugs.
Cons: It might break compatibility with your code.

compile 'com.google.code.gson:gson:+'

Using Gson to load a JSON file from disk.

This will load a JSON file from disk and convert it to the given type.

public static <T> T getFile(String fileName, Class<T> type) throws FileNotFoundException {
    Gson gson = new GsonBuilder()
            .create();
    FileReader json = new FileReader(fileName);
    return gson.fromJson(json, type);
}

Adding a custom Converter to Gson

Sometimes you need to serialize or deserialize some fields in a desired format, for example your backend may use the format "YYYY-MM-dd HH:mm" for dates and you want your POJOS to use the DateTime class in Joda Time.

In order to automatically convert these strings into DateTimes object, you can use a custom converter.

/**
 * Gson serialiser/deserialiser for converting Joda {@link DateTime} objects.
 */
public class DateTimeConverter implements JsonSerializer<DateTime>, JsonDeserializer<DateTime> {

    private final DateTimeFormatter dateTimeFormatter;

    @Inject
    public DateTimeConverter() {
        this.dateTimeFormatter = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm");
    }

    @Override
    public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(dateTimeFormatter.print(src));
    }

    @Override
    public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        
        if (json.getAsString() == null || json.getAsString().isEmpty()) {
            return null;
        }

        return dateTimeFormatter.parseDateTime(json.getAsString());
    }
}

To make Gson use the newly created converter you need to assign it when creating the Gson object:

    DateTimeConverter dateTimeConverter = new DateTimeConverter();
    Gson gson = new GsonBuilder().registerTypeAdapter(DateTime.class, dateTimeConverter)
            .create();

    String s = gson.toJson(DateTime.now());
    // this will show the date in the desired format

In order to deserialize the date in that format you only have to define a field in the DateTime format:

public class SomePojo {
    private DateTime someDate;    
} 

When Gson encounters a field of type DateTime, it will call your converter in order to deserialize the field.

Using Gson as serializer with Retrofit

First of all you need to add the GsonConverterFactory to your build.gradle file

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

Then, you have to add the converter factory when creating the Retrofit Service:

Gson gson = new GsonBuilder().create();
new Retrofit.Builder()
        .baseUrl(someUrl)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()
        .create(RetrofitService.class);

You can add custom converters when creating the Gson object that you are passing to the factory. Allowing you to create custom type conversions.

Parsing json array to generic class using Gson

Suppose we have a json :

{
  "total_count": 132,
  "page_size": 2,
  "page_index": 1,
  "twitter_posts": [
    {
      "created_on": 1465935152,
      "tweet_id": 210462857140252672,
      "tweet": "Along with our new #Twitterbird, we've also updated our Display Guidelines",
      "url": "https://twitter.com/twitterapi/status/210462857140252672"
    },
    {
      "created_on": 1465995741,
      "tweet_id": 735128881808691200,
      "tweet": "Information on the upcoming changes to Tweets is now on the developer site",
      "url": "https://twitter.com/twitterapi/status/735128881808691200"
    }
  ]
}

We can parse this array into a Custom Tweets (tweets list container) object manually, but it is easier to do it with fromJson method:

Gson gson = new Gson();
String jsonArray = "....";
Tweets tweets = gson.fromJson(jsonArray, Tweets.class);

Suppose we have two classes below:

class Tweets {
    @SerializedName("total_count")
    int totalCount;
    @SerializedName("page_size")
    int pageSize;
    @SerializedName("page_index")
    int pageIndex;
    // all you need to do it is just define List variable with correct name 
    @SerializedName("twitter_posts")
    List<Tweet> tweets;
}

class Tweet {
    @SerializedName("created_on")
    long createdOn;
    @SerializedName("tweet_id")
    String tweetId;
    @SerializedName("tweet")
    String tweetBody;
    @SerializedName("url")
    String url;
}

and if you need just parse a json array you can use this code in your parsing:

String tweetsJsonArray = "[{.....},{.....}]"
List<Tweet> tweets = gson.fromJson(tweetsJsonArray, new TypeToken<List<Tweet>>() {}.getType());

Custom JSON Deserializer using Gson

Imagine you have all dates in all responses in some custom format, for instance /Date(1465935152)/ and you want apply general rule to deserialize all Json dates to java Date instances. In this case you need to implement custom Json Deserializer.

Example of json:

{
  "id": 1,
  "created_on": "Date(1465935152)",
  "updated_on": "Date(1465968945)",
  "name": "Oleksandr"
}

Suppose we have this class below:

class User {
    @SerializedName("id")
    long id;
    @SerializedName("created_on")
    Date createdOn;
    @SerializedName("updated_on")
    Date updatedOn;
    @SerializedName("name")
    String name;
}

Custom deserializer:

class DateDeSerializer implements JsonDeserializer<Date> {
    private static final String DATE_PREFIX = "/Date(";
    private static final String DATE_SUFFIX = ")/";

    @Override
    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        String dateString = json.getAsString();
        if (dateString.startsWith(DATE_PREFIX) && dateString.endsWith(DATE_SUFFIX)) {
            dateString = dateString.substring(DATE_PREFIX.length(), dateString.length() - DATE_SUFFIX.length());
        } else {
            throw new JsonParseException("Wrong date format: " + dateString);
        }
        return new Date(Long.parseLong(dateString) - TimeZone.getDefault().getRawOffset());
    }
}

And the usage:

Gson gson = new GsonBuilder()
                .registerTypeAdapter(Date.class, new DateDeSerializer())
                .create();
String json = "....";
User user = gson.fromJson(json, User.class);

Serialize and deserialize Jackson JSON strings with Date types

This also applies to the case where you want to make Gson Date conversion compatible with Jackson, for example.

Jackson usually serializes Date to "milliseconds since epoch" whereas Gson uses a readable format like Aug 31, 2016 10:26:17 to represent Date. This leads to JsonSyntaxExceptions in Gson when you try to deserialize a Jackson format Date.

To circumvent this, you can add a custom serializer and a custom deserializer:

JsonSerializer<Date> ser = new JsonSerializer<Date>() {
    @Override
    public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext
                context) {
        return src == null ? null : new JsonPrimitive(src.getTime());
    }
};

JsonDeserializer<Date> deser = new JsonDeserializer<Date>() {
    @Override
    public Date deserialize(JsonElement json, Type typeOfT,
                JsonDeserializationContext context) throws JsonParseException {
        return json == null ? null : new Date(json.getAsLong());
    }
};

Gson gson = new GsonBuilder()
                .registerTypeAdapter(Date.class, ser)
                .registerTypeAdapter(Date.class, deser)
                .create();

Using Gson with inheritance

Gson does not support inheritance out of the box.

Let's say we have the following class hierarchy:

public class BaseClass {
    int a;
 
    public int getInt() {
        return a;
   }
}
 
public class DerivedClass1 extends BaseClass {
     int b;
 
     @Override
     public int getInt() {
         return b;
     }
 }
 
public class DerivedClass2 extends BaseClass {
    int c;
 
    @Override
    public int getInt() {
        return c;
    }
}

And now we want to serialize an instance of DerivedClass1 to a JSON string

DerivedClass1 derivedClass1 = new DerivedClass1();
derivedClass1.b = 5;
derivedClass1.a = 10;
 
Gson gson = new Gson();
String derivedClass1Json = gson.toJson(derivedClass1);

Now, in another place, we receive this json string and want to deserialize it - but in compile time we only know it is supposed to be an instance of BaseClass:

BaseClass maybeDerivedClass1 = gson.fromJson(derivedClass1Json, BaseClass.class);
System.out.println(maybeDerivedClass1.getInt());

But GSON does not know derivedClass1Json was originally an instance of DerivedClass1, so this will print out 10.

How to solve this?

You need to build your own JsonDeserializer, that handles such cases. The solution is not perfectly clean, but I could not come up with a better one.

First, add the following field to your base class

@SerializedName("type")
private String typeName;

And initialize it in the base class constructor

public BaseClass() {
    typeName = getClass().getName();
}

Now add the following class:

public class JsonDeserializerWithInheritance<T> implements JsonDeserializer<T> {
 
 @Override
 public T deserialize(
     JsonElement json, Type typeOfT, JsonDeserializationContext context)
     throws JsonParseException {
     JsonObject jsonObject = json.getAsJsonObject();
     JsonPrimitive classNamePrimitive = (JsonPrimitive) jsonObject.get("type");
 
     String className = classNamePrimitive.getAsString();
 
     Class<?> clazz;
     try {
     clazz = Class.forName(className);
     } catch (ClassNotFoundException e) {
     throw new JsonParseException(e.getMessage());
     }
     return context.deserialize(jsonObject, clazz);
 }
}

All there is left to do is hook everything up -

GsonBuilder builder = new GsonBuilder();
 builder
 .registerTypeAdapter(BaseClass.class, new JsonDeserializerWithInheritance<BaseClass>());
 Gson gson = builder.create();

And now, running the following code-

 DerivedClass1 derivedClass1 = new DerivedClass1();
 derivedClass1.b = 5;
 derivedClass1.a = 10;
 String derivedClass1Json = gson.toJson(derivedClass1);
 
 BaseClass maybeDerivedClass1 = gson.fromJson(derivedClass1Json, BaseClass.class);
 System.out.println(maybeDerivedClass1.getInt());

Will print out 5.

Syntax:

  • Excluder excluder()
  • FieldNamingStrategy fieldNamingStrategy()
  • <T> T fromJson(JsonElement json, Class<T> classOfT)
  • <T> T fromJson(JsonElement json, Type typeOfT)
  • <T> T fromJson(JsonReader reader, Type typeOfT)
  • <T> T fromJson(Reader json, Class<T> classOfT)
  • <T> T fromJson(Reader json, Type typeOfT)
  • <T> T fromJson(String json, Class<T> classOfT)
  • <T> T fromJson(String json, Type typeOfT)
  • <T> TypeAdapter<T> getAdapter(Class<T> type)
  • <T> TypeAdapter<T> getAdapter(TypeToken<T> type)
  • <T> TypeAdapter<T> getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken<T> type)
  • JsonReader newJsonReader(Reader reader)
  • JsonWriter newJsonWriter(Writer writer)
  • JsonElement toJsonTree(Object src)
  • JsonElement toJsonTree(Object src, Type typeOfSrc)
  • boolean serializeNulls()
  • boolean htmlSafe()
  • String toJson(JsonElement jsonElement)
  • String toJson(Object src)
  • String toJson(Object src, Type typeOfSrc)
  • String toString()
  • void toJson(Object src, Type typeOfSrc, Appendable writer)
  • void toJson(Object src, Type typeOfSrc, JsonWriter writer)
  • void toJson(JsonElement jsonElement, Appendable writer)
  • void toJson(JsonElement jsonElement, JsonWriter writer)
  • void toJson(Object src, Appendable writer)

Contributors

Topic Id: 4158

Example Ids: 3394,6019,10755,10997,14591,14797,14798,14799,14800,15338,15339,17697

This site is not affiliated with any of the contributors.