[Gson 8] GsonBuilder 서열화 및 반서열화 옵션 enable ComplexMapKey Serialization

10612 단어 serialization

enableComplexMapKeySerialization 구성 항목의 의미


Gson은 Map을 서열화할 때 기본적으로 키의 tostring 방법을 호출하여 JSON 문자열을 얻는 키입니다. 간단한 형식과 문자열 형식에 대해서는 문제가 없지만 복잡한 데이터 대상에 대해서는 대상이 tostring 방법을 덮어쓰지 않으면 기본적인 tostring 방법은 이 대상의Hash 주소를 얻을 수 있습니다.
 
GsonBuilder는 Gson 객체 작성을 위한 구성 옵션을 설정합니다. 이러한 옵션은 Gson gson = new Gson()을 통해 작성된 Gson 객체(예: 다음 예제 코드)를 덮어씁니다.
 

enable ComplexMapKeySerialization을 사용하지 않고 유형 어댑터를 시작하지 않음(PointTypeAdapter)


 
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

class Point {
    private  int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}



public class Test {

    public static void main(String[]args) {

        Map<Point, String> map = new HashMap<Point, String>();
        Point p1 = new Point();
        p1.setX(10);
        p1.setY(10);
        map.put(p1, "Ten");

        Point p2 = new Point();
        p2.setX(20);
        p2.setY(20);
        map.put(p2, "Twenty");

        Gson gson  = new GsonBuilder().create();
        String str = gson.toJson(map);
        System.out.println(str);//{"test1.Point@5ba5ba75":"Ten","test1.Point@5d748654":"Twenty"}

        Type type = new TypeToken<Map<Point,String>>(){}.getType();

        map  = gson.fromJson(str, type);//java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
    }
}

코드 출력 {"Point@6f92c766":"Twenty","Point@6406c7e":"Ten "}, Key가 문자열로 변환될 때 사용하는 Key. to String () 방법 (여기 있는 Key는 Point 형식) 을 볼 수 있습니다. 이 변환 결과는 기본적으로 받아들일 수 없습니다. 서열화된 JSON 문자열은 원래의 Map 집합을 반서열화할 수 없기 때문입니다. 위의 반서열화할 때, Gson이Point@6f92c766단순한 문자열일 뿐 Point로 변환할 수 없습니다.
 

enable ComplexMapKeySerialization 구성 항목을 사용하지만 유형 어댑터는 사용하지 않습니다.


enableComplexMapKeySerialization 설정 항목만 사용하지만 Point 클래스의 사용자 정의 형식 어댑터를 사용하지 않으면 이 맵은 JSON 그룹으로 서열화되고 그룹의 모든 요소도 하나의 그룹입니다. 이 그룹의 길이는 2이고, 첫 번째 값은 Key가 변환한 JSON 대상 문자열이며, 두 번째 값은Value에 대응하는 JSON 문자열입니다.코드는 다음과 같습니다.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

class Point {
    private int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}
public class Test {
    public static void main(String[] args) {
        Map<Point, String> map = new HashMap<Point, String>();
        Point p1 = new Point();
        p1.setX(10);
        p1.setY(10);
        map.put(p1, "Ten");

        Point p2 = new Point();
        p2.setX(20);
        p2.setY(20);
        map.put(p2, "Twenty");

        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.enableComplexMapKeySerialization();
        Gson gson = gsonBuilder.create();
        String str = gson.toJson(map);
        System.out.println(str); //[[{"x":10,"y":10},"Ten"],[{"x":20,"y":20},"Twenty"]]
        Type type = new TypeToken<Map<Point, String>>(){}.getType();
        map = gson.fromJson(str, type); // 
    }

}
 
 

enableComplexMapKeySerialization 구성 항목을 활성화하고 유형 어댑터를 활성화합니다.


 
 
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

class Point {
    private int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

class PointTypeAdapter extends TypeAdapter<Point> {

    @Override
    public void write(JsonWriter out, Point value) throws IOException {
        if (value == null) {
            out.nullValue();
        } else {
            out.value("(" + value.getX() + "," + value.getY() + ")");
        }
    }

    @Override
    public Point read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            return null;
        } else {
            String str = in.nextString(); 
            str = str.substring(1, str.length() - 1); // writer , 
            String[] pair = str.split(",");
            Point p =  new Point();
            p.setX(Integer.parseInt(pair[0]));
            p.setY(Integer.parseInt(pair[1]));
            return p;
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Map<Point, String> map = new HashMap<Point, String>();
        Point p1 = new Point();
        p1.setX(10);
        p1.setY(10);
        map.put(p1, "Ten");

        Point p2 = new Point();
        p2.setX(20);
        p2.setY(20);
        map.put(p2, "Twenty");

        Gson gson = new GsonBuilder().enableComplexMapKeySerialization().registerTypeAdapter(Point.class, new PointTypeAdapter()).create();
        String str = gson.toJson(map);
        System.out.println(str); //{"(10,10)":"Ten","(20,20)":"Twenty"}
        Type type = new TypeToken<Map<Point, String>>() {
        }.getType();
        map = gson.fromJson(str, type); // 
    }

}

 
 

유형 어댑터는 활성화되지만 enable ComplexMapKeySerialization은 활성화되지 않습니다.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

class Point {
    private int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

class PointTypeAdapter extends TypeAdapter<Point> {

    @Override
    public void write(JsonWriter out, Point value) throws IOException {
        if (value == null) {
            out.nullValue();
        } else {
            out.value("(" + value.getX() + "," + value.getY() + ")");
        }
    }

    @Override
    public Point read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            return null;
        } else {
            String str = in.nextString(); 
            str = str.substring(1, str.length() - 1); // writer , 
            String[] pair = str.split(",");
            Point p =  new Point();
            p.setX(Integer.parseInt(pair[0]));
            p.setY(Integer.parseInt(pair[1]));
            return p;
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Map<Point, String> map = new HashMap<Point, String>();
        Point p1 = new Point();
        p1.setX(10);
        p1.setY(10);
        map.put(p1, "Ten");

        Point p2 = new Point();
        p2.setX(20);
        p2.setY(20);
        map.put(p2, "Twenty");

        Gson gson = new GsonBuilder().registerTypeAdapter(Point.class, new PointTypeAdapter()).create();
        String str = gson.toJson(map);
        System.out.println(str); //{"Point@e0cc23":"Twenty","Point@76ab2f":"Ten"}
        Type type = new TypeToken<Map<Point, String>>() {
        }.getType();
        map = gson.fromJson(str, type); // 
    }

}

 
위 코드가 PointType Adapter만 등록하고 enable Complex MapKey Serialization을 호출하지 않으면 서열화된 결과는 여전히 {"Point@e0cc23":"Twenty","Point@76ab2f":"Ten"}
 

총결산


 1.Map 형식의 대상을 서열화할 때, 키가 복잡한 데이터 형식 (기본 데이터 형식이나 String, 즉 사용자 정의 POJO) 이 아니라면, 이때는 enable Complex MapKey Serialization 설정 옵션을 사용해야 합니다. 그렇지 않으면 Gson은 기본적으로 Key입니다.toString()은 JSON 문자열에 해당하는 Key입니다.
 2.실제적으로 번거로운 것은 JSON 문자열의 구조에 따라 대응하는 POJO를 정의하는 것이다. 만약에 JSON 열에서 키가 JSON 대상 형식이라면 맵을 사용하고 키를 복잡한 유형으로 정의한 다음에 enable Complex Map Key Serialization 옵션을 사용하고 Type Adapter를 등록하는 것을 고려할 수 있다.
 
 
 
 
 
 
 

좋은 웹페이지 즐겨찾기