Gson: Google’s Java JSON parser, GitHub superscript star 18K

Time:2021-6-9

01. Past and present

My name is gson. It is an open source Java library. Its main purpose is to serialize Java objects into JSON strings, or to deserialize JSON strings into Java objects. From my name, you can see some clues. I’m not a nameless person. I’m from a noble family. My father is Google, and the market value is as rich as the world.

Of course, as a smart person, I have self-knowledge. In my father’s eyes, I am not the most shining star.

It was an accident that I came to this world. Anyway, my father told me that. He always said that I picked it up from the river, although I didn’t believe it. For this matter, I confirmed to my mother, she listened to the smile, said I was too naive.

When I grew up, I liked to wander around, so I got to know a lot of my peers, some of themJacksonandFastjson

Speaking of Jackson, I can always think of MJ, the pop king who was taken away by God for the first time. Jackson has a 6.1k star on GitHub. Although he doesn’t have as many fans as I do, as the default JSON parser of spring boot, I respect him very much.

Fastjson comes from the mysterious East. Although there have been some serious loopholes, it does not prevent him from becoming the most popular JSON parser. He has more fans than me, even though I have more than 18K stars.

Outsiders always say that we are competitors, but I have to tell them that the relationship between the three of us is so good that we have to wear the same pair of underwear.

We have our own advantages. Jackson uses less memory at runtime, and fastjson is faster. I can handle any Java object, even without source code. In addition, my support for generics is also more friendly.

02. Add dependency

Before using my API, you need to add me to the project. Maven and gradle are recommended.

Maven:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

Gradle:

dependencies {
  implementation 'com.google.code.gson:gson:2.8.6'
}

PS: gradle is a project automation tool based on Apache ant and Apache Maven concepts. Gradle build scripts are written in groovy or kotlin’s domain specific language, not traditional XML.

03. Performance

No, I think it’s true. A lot of tests have proved that I am still very good at handling JSON.

Test environment: dual core, 8g memory, 64 bit Ubuntu operating system (Linux distribution based on desktop application)

Test results:

1) There was no problem in deserializing strings larger than 25m.

2) A collection of 1.4 million objects can be serialized.

3) You can deserialize a collection of 87000 objects.

4) The deserialization limit of byte array and collection is increased from 80K to 11m.

I have written the test cases for you and put them on GitHub. If you don’t believe it, you can verify it.

https://github.com/google/gso…

04. Use guide

It’s not that I boast, it’s true. I’m still very good at it, and the difficulty is almost zero. If you don’t believe it, you can try it.

I have a girlfriend whose name is the same as mineGsonMy main functions are provided by her. You can go throughnew Gson()You can also call a boss named gsonbuilder and ask him to mail a copy. Really, I won’t cheat you.

Let’s start with an example of serialization.

Gson gson = new Gson();
System.out.println(gson.toJson(18));
System. Out. Println (gson. Tojson ("Silence"));
System.out.println(gson.toJson(new Integer(18)));
int[] values = { 18,20 };
System.out.println(gson.toJson(values));

With the help of my girlfriend, you can pass basic data type int, string type string, wrapper type integer, int array and so on as parameters totoJson()Method, which returns a string in the form of JSON.

Take a look at the output:

18
"Silence"
18
[18,20]

Let’s look at the example of deserialization.

Gson gson = new Gson();
int one = gson.fromJson("1", int.class);
Integer two = gson.fromJson("2", Integer.class);
Boolean false1 = gson.fromJson("false", Boolean.class);
String STR = gson. Fromjson ("\" Wang Er \ ", string. Class);
String [] otherstr = gson. Fromjson ("[" Silence ", \" Wang Er "], string [] class);

System.out.println(one);
System.out.println(two);
System.out.println(false1);
System.out.println(str);
System.out.println(Arrays.toString(anotherStr));

toJson()Method is used for serialization,fromJson()Method is used for deserialization. However, when deserializing, you need to specify the type of parameters, such as int or integer, Boolean or string, or string array.

Take a look at the output:

1
2
false
WangTwo 
[沉默, WangTwo ]

The above examples are relatively simple, and can not reflect my power.

Next, let’s customize a class

public class Writer {
    private int age = 18;
    Private string name = Wang Er;
    private transient int sex = 1;
}

Then, let’s serialize it:

Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);

The usage is as simple as before. Let’s take a look at the output

{age: 18, name: Wang Er}

Similarly, you can deserialize the results:

Writer writer1 = gson.fromJson(json, Writer.class);

Here are some points for attention, I need to remind you.

1) RecommendedprivateModify the field.

2) No annotations are needed to indicate which fields need to be serialized and which fields do not. By default, it includes all fields and fields inherited from the parent class.

3) If a field istransientKeyword modification, it will not participate in serialization.

4) If the value of a field is null, it will not be displayed in the serialized result.

5) The missing fields in JSON will be set to the default value after deserialization, the default value of reference data type is null, the default value of number type is 0, and the default value of Boolean value is false.

Next, let’s look at an example of a serialized collection.

List<String> list =new ArrayList<>();
List. Add ("study hard");
List. Add ("day up");
String json = gson.toJson(list);

The results are as follows

["study hard", "make progress every day"]

When deserializing, it’s also very simple.

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

The results are as follows

[study hard and make progress every day]

My girlfriend is a very careful and considerate person, when you calltoJson()When the method is serialized, it will judge null first to prevent NPE from being thrown, and then pass thegetClass()Gets the type of the parameter and serializes it.

public String toJson(Object src) {
    if (src == null) {
        return toJson(JsonNull.INSTANCE);
    }
    return toJson(src, src.getClass());
}

But what? For generics,getClass()The parameterized type will be lost when the parameter is changed. Here’s an example.

public class Foo<T> {
    T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

    public static void main(String[] args) {
        Gson gson = new Gson();
        Foo<Bar> foo = new Foo<Bar>();
        Bar bar = new Bar();
        foo.set(bar);

        String json = gson.toJson(foo);
    }
}

class Bar{
    private int age = 10;
    Private string name = Turing;
}

If you debug, go totoJson()The interior of the method can be observed.

Gson: Google's Java JSON parser, GitHub superscript star 18K

The actual type of foo isFoo<Bar>But my girlfriend is callingfoo.getClass()She only gets foo, which means she doesn’t know the actual type of foo.

It’s OK when serializing, but it’s useless when deserializing.

Foo<Bar> foo1 = gson.fromJson(json, foo.getClass());
Bar bar1 = foo1.get();

This code will report an error when it is running.

Exception in thread "main" java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.itwanger.gson.Bar (com.google.gson.internal.LinkedTreeMap and com.itwanger.gson.Bar are in unnamed module of loader 'app')
    at com.itwanger.gson.Foo.main(Foo.java:36)

By default, the generic parameter type will be converted to linkedtreemap, which is obviously not the bar we expected. My girlfriend is very helpless about this.

As Google’s own son, I have the word “noble” flowing in my blood. How can I bear the loneliness when my girlfriend is helpless.

So, I implanted two other methods into my girlfriend’s body, one with type parameter:

toJson(Object src, Type typeOfSrc);
<T> T fromJson(String json, Type typeOfT);

In this way, when you serialize and deserialize a generic, you can specify the parameterized type of the generic.

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
String json = gson.toJson(foo,fooType);
Foo<Bar> foo1 = gson.fromJson(json, fooType);
Bar bar1 = foo1.get();

Debug intoJson()Method, you can see the real type of foo.

Gson: Google's Java JSON parser, GitHub superscript star 18K

fromJson()In deserialization, it’s similar.

Gson: Google's Java JSON parser, GitHub superscript star 18K

In this way, bar1 can passfoo1.get()here we are.

Look, how thoughtful I am! My girlfriend can’t help praising me!

05. Treatment mix type

As you know, Java does not recommend using mixed types, which is the case below.

List list = new ArrayList();
List. Add ("silent Wang Er");
list.add(18);
list.add(new Event("gson", "google"));

Event is defined as follows:

class Event {
    private String name;
    private String source;
    Event(String name, String source) {
        this.name = name;
        this.source = source;
    }
}

Since the list does not specify a specific type, it can store various types of data. Although it’s easy, my girlfriend has no problem in serialization, but it’s much more troublesome in deserialization.

Gson gson = new Gson();
String json = gson.toJson(list);
System.out.println(json);

The output results are as follows:

["silent King II", 18, {"name": "gson", "source": "Google"}]

When deserializing, you need to work hard to get the event object.

JsonParser parser = new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1), int.class);
Event event = gson.fromJson(array.get(2), Event.class);

Yes, Jason parser is my predecessor. I hope you don’t spray me scum man, it’s not my playboy, it’s because our character is not suitable. But we still maintain the relationship of friends, because none of us is wrong, but the code is more standardized, and few developers use mixed types.

06. Personalized customization

Considering that you are a fashionable person, I have always been very demanding of myself, and strive to meet all your needs. This high standard makes my girlfriend love and hate me.

What I love is my attitude of pursuing perfection; What I hate is that sometimes she can’t help.

usetoJson()When serializing Java objects, there is no space in the returned JSON string, which is very compact. If you want to print a more beautiful JSON format, you need to call a boss named gsonbuilder, ask him to make some customization, and then mail the copy to you, just like I did in theGuide to useAs mentioned in.

public class Writer {
    private int age = 18;
    Private string name = "silent Wang Er";

    public static void main(String[] args) {
        Writer writer = new Writer();
        Gson gson = new Gson();
        String json = gson.toJson(writer);
        System.out.println(json);

        Gson gson1 = new GsonBuilder().setPrettyPrinting().create();
        String jsonOutput = gson1.toJson(writer);
        System.out.println(jsonOutput);
    }
}

To compare the output results:

{"age": 18, "name": "silent Wang Er"}
{
  "age": 18,
  "Name": "silent Wang Er"
}

adoptsetPrettyPrinting()After customization, the output format is more hierarchical and three-dimensional, with spaces between fields and values, and line breaks between different fields.

As mentioned earlier, by default, my girlfriend ignores null fields when serializing. If she doesn’t want to, she can also call gsonbuilder.

public class Writer {
    private int age = 18;
    private String name = null;

    public static void main(String[] args) {
        Writer writer = new Writer();
        Gson gson = new Gson();
        String json = gson.toJson(writer);
        System.out.println(json);

        Gson gson2 = new GsonBuilder().serializeNulls().create();
        String jsonOutput2 = gson2.toJson(writer);
        System.out.println(jsonOutput2);
    }
}

To compare the output results:

{"age":18}
{"age":18,"name":null}

adoptserializeNulls()After customization, fields with null values will no longer be ignored in serialization.

Maybe you want to filter some fields when you serialize and deserialize. I have also considered this requirement, and specially prepared several schemes for you. You can choose the one suitable for you according to your own taste.

First, through Java modifiers

As you’ve seen before, usingtransientKeyword decorated fields will not participate in serialization and deserialization. alike,staticFields decorated with keywords will not. If you want to keep the fields decorated by these keywords, you can do so.

Keep single species.

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

Keep a variety.

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

Second, through the@Exposeannotation

To use@ExposeNote, you need to do this first:

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

Add the@ExposeNote, if not added, this field will be ignored.

@Expose
private int age = 18;

07. Voice of the heart

If you want to know more, please visit my GitHub homepage:

https://github.com/google/gson

I will tell you all about me, without reservation, except for some secrets between me and my girlfriend, just to help you.

If you think I’m useful, you might as well give me a compliment and leave a message.

Recommended reading

Please, don’t ask me how to teach myself java! emerge in its totality

Take my sister into the pit, how can she improve her programming ability?