Gson is an open-source JSON library from Google, which is widely used in Android development.

Note: All of the following uses are based on the Account class!

public class Account { private String uid; private String userName; private String password; private String telNumber; public Account(String uid, String userName, String telNumber) { this.uid = uid; this.userName = userName; this.telNumber = telNumber; } @Override public String toString() { return "Account [uid=" + uid + ", userName=" + userName + ", password=" + password + ", telNumber=" + telNumber + "]"; }}Copy the code

Basic usage

Integrated Gson

Dependencies {implementation 'com. Google. Code. Gson: gson: 2.8.5'}Copy the code

Create a Gson object

Gson provides two ways to create objects:

  1. Create directly using the Gson constructor;

    Gson gson = new Gson();

  2. Create using GsonBuilder;

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

The way GsonBuilder is created is more flexible than using constructors directly because it supports configuration of Gson.

Convert the object to JSON

Account account = new Account("00001", "Freeman", "13000000000");
System.out.println(gson.toJson(account));
	
ArrayList<Account> accountList = new ArrayList<Account>();
accountList.add(account);
System.out.println(gson.toJson(accountList));
Copy the code

Results:

{"uid":"00001","userName":"Freeman","telNumber":"13000000000"}
[{"uid":"00001","userName":"Freeman","telNumber":"13000000000"}]
Copy the code

Convert JSON to objects

Because of the type erasure problem with generics in Java, using generics to receive JSON parsing results is a bit special.

Ordinary object parsing
String json = "{\"uid\":\"00001\",\"userName\":\"Freeman\",\"telNumber\":\"13000000000\"}";
Account receiveAccount = gson.fromJson(json, Account.class);
System.out.println(receiveAccount.toString());
Copy the code

Results:

Account [uid=00001, userName=Freeman, password=null, telNumber=13000000000]
Copy the code
Generic object resolution
String listJson = "[{\"uid\":\"00001\",\"userName\":\"Freeman\",\"telNumber\":\"13000000000\"}]";
List receiveAccountList = gson.fromJson(listJson, new TypeToken<List<Account>>(){}.getType());
System.out.println("receiveAccountList size = " + receiveAccountList.size());
Copy the code

Results:

receiveAccountList size = 1
Copy the code

Field reuse

Bean objects are sometimes reused during development, but there may be several fields that are named differently from the current object, so that the values are not assigned correctly when parsing JSON. Gson provides field reuse — @serializedName, which accepts different JSON fields from a single field.

@serializedName ("phone") Private String telNumber; // JSON The phone number field in the String can be correctly resolved if it is phone or telNumber. @serializedName (value = "userName", alternate = {"user_name", "uname", "u_name"}) private String userName;Copy the code

Gson configuration

In addition to the above usage, Gson provides a wealth of configuration options, including: null value filtering, field naming rules, custom parsers, custom serialization/deserialization, and more.

A null value problem

Gson filters empty fields by default, but sometimes when submitting data to the background, even if the field is empty, it needs to be passed to the background. In this case, you can configure it using GsonBuilder.

gson = new GsonBuilder().serializeNulls().create();
Account account = new Account("00001", "Freeman", "13000000000");
System.out.println(gson.toJson(account));
Copy the code

Results:

{"uid":"00001","userName":"Freeman","password":null,"phone":"13000000000"}
Copy the code

As you can see from the result, the password field is output, whereas the previous Gson transformation did not output the password field.

Field name conversion rules

Because different languages use different naming conventions, it can occur to use field names that do not conform to the naming conventions in order to parse the JSON string properly. For example, PHP uses the lowercase underscore naming method, while Java uses the camel naming method, so Android applications need to use the lowercase underscore naming method when receiving JSON strings, but this does not comply with the Java naming convention. To solve this problem, Gson provides rich field naming conventions.

/ / the default field transformation rules, the field name unchanged FieldNamingPolicy. IDENTITY () / / field names from the json conversion, led by the format of the letter of FieldNamingPolicy. UPPER_CAMEL_CASE () such as: "User_name" -> "UserName" fieldnamingPolicy.upper_camel_case_with_spaces () "User_name" -> "User Name" // Convert field names in JSON to lowercase letters and underscores () "UserName" -> "user_name" // Convert the name of the field in json to lowercase letters. "UserName" -> "user-name"Copy the code

So if the server is PHP, the Android side can use the fieldNamingPolicy. UPPER_CAMEL_CASE conversion rule.

Gson gson = new GsonBuilder()
	.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
	.create();
Copy the code

Of course, if the above naming transformation rules do not meet the requirements, you can also customize the naming transformation rules by implementing the FieldNamingStrategy interface and perfecting the translateName method. Note that the naming conversion rules apply to both serialization and deserialization, so be careful when converting an object to JSON(serialization) and passing it to the background.

Field filtering

By default, when Gson converts an object to JSON, all non-NULL fields are converted, but sometimes for business purposes, it is common to add some status fields, such as isSelected, which represents the status of the item selection, that are not expected to be converted. Gson offers a variety of filtering methods, but here are the two most commonly used.

  1. Filter by modifier

    Gson Gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC) .create();

  2. User-defined filtering rules

Filter rules are defined by implementing the setExclusionStrategies interface:

ExclusionStrategy strategy = new ExclusionStrategy() { @Override public boolean shouldSkipClass(Class<? > arg0) {// Filter the specified class return false; } @override public Boolean shouldSkipField(FieldAttributes arg0) {return false; }}; Gson Gson = new GsonBuilder() // Filter rules for both serialization/deserialization. SetExclusionStrategies (strategy) // Filter rules for serialization only . AddSerializationExclusionStrategy (strategy) / / filter rule only applies to deserialize addDeserializationExclusionStrategy (strategy). The create ();Copy the code

Field fault tolerance

Field fault tolerance is mainly reflected in the mismatch of field types. For example, the received field is an integer, but the returned field is a String or NULL. In this case, it can be solved by using String to receive an integer, but for the case that the received type is array and the returned object, it cannot be directly handled by using type compatibility.

Although these cases are due to background data format problems, but the most intuitive feeling for users is the APP flash back. Therefore, we need to make certain compatible processing for the JSON parsing process to prevent the APP from flashing back when abnormal data occurs.

Summary of common type compatibility issues encountered in development:

  1. Received with type Number, which returns a String or null value (Gson has dealt with such issues);
  2. Using an array receiver, the object type is returned;

Gson provides a variety of serialization/deserialization methods. Since we only do compatibility processing of JSON parsing (deserialization) here, we can directly implement JsonDeserializer interface.

JsonDeserializer<List<? >> listDeserial = new JsonDeserializer<List<? >>() { @Override public List<? > deserialize(JsonElement arg0, java.lang.reflect.Type arg1, JsonDeserializationContext arg2) throws JsonParseException { if (arg0.isJsonArray()) { JsonArray jsonArray = arg0.getAsJsonArray(); if (jsonArray.size() == 0) { return Collections.EMPTY_LIST; } List<? > resultList = new ArrayList<>(); for (JsonElement element : jsonArray) { resultList.add(arg2.deserialize(element, arg1)); } return resultList; } else { return Collections.EMPTY_LIST; }}}; Gson Gson = new GsonBuilder () / / registered custom deserialization adapter. RegisterTypeHierarchyAdapter (List. Class, listDeserial). The create ();Copy the code

Summary of common Gson configurations

Gson = new GsonBuilder() // do not filter null values. SerializeNulls () // Set the field name conversion rule .setfieldNamingPolicy (fieldNamingPolicy.upper_camel_case) // Sets filter rules for field serialization/deserialization ExcludeFieldsWithModifiers (Modifier. The TRANSIENT Modifier. The STATIC) parser / / custom types, Improve Gson fault-tolerance. RegisterTypeHierarchyAdapter (List. Class, listDeserial). The create ();Copy the code

conclusion

The above is just some summary of the process of using Gson, which involves a lot of details, such as JSON parsing process, type matching, etc., are not mentioned, interested can read its source code.