GSON은 JSON과 Java 객체 간의 상호 변환을 구현하는 데 사용되는 Java 라이브러리입니다. GSON은 https://github.com/google/gson에서 개최되는 오픈 소스 프로젝트입니다.
GSON의 주요 클래스는 GSON입니다. GSON 객체를 만드는 동안 클래스 GSONBUILDER를 사용하여 일부 옵션을 설정할 수도 있습니다.
GSON 객체는 JSON을 처리 할 때 상태를 저장하지 않으므로 사용자는 동일한 GSON 객체에서 여러 직렬화, 사막화 및 기타 작업을 쉽게 수행 할 수 있습니다.
예 : 기본 사용
// serializationgson gson = new gson (); gson.tojson (1); // ==> 인쇄 1gson.tojson ( "ABCD"); // ==> "ABCD"GSON.TOJSON (New Long (10)); // ==> 인쇄 10int [] value = {1}; gson.tojson (값); // ==> prints [1] // deserializationint one = gson.fromjson ( "1", int.class); integer one = gson.fromjson ( "1", integer.class); long one = gson.fromjson ( "1", integer.class); long one = gson.fromjson ( "1", boolans); gson.fromjson ( "false", boolean.class); String str = gson.fromjson ( "/"abc/"", string.class); String anotherstr = gson.fromjson ( "[/"abc/"]", string.class); // serializationbagofprimitives obj = new bagofprimitives (); gson = new Gson (); gson.tojson (obj); // ==> JSON은 { "value1": 1, "value2": "ABC"}입니다.예 : 물체와 JSON 간의 변환
Bagof -Primitives 클래스 정의 :
클래스 bagof -primitives {private int value1 = 1; 개인 문자열 value2 = "abc"; 비공개 과도 int value3 = 3; bagofprimitives () {// no-args 생성자}}}JSON에 직렬화 :
// SerializationbagofPrimitives obj = new BagofPrimitives (); gson gson = new gson (); String json = gson.tojson (obj); // ==> JSON은 { "value1": 1, "value2": "ABC"}입니다.원형 참조를 포함하는 객체를 직렬화하지 마십시오. 그렇지 않으면 무한 재귀가 발생합니다.
사제화 :
// deserializationbagofprimitives obj2 = gson.fromjson (json, bagofprimitives.class); // ==> OBJ2는 OBJ와 같습니다
개체를 처리 할 때 일부 세부 사항 :
중첩 클래스 처리 (내부 수업 포함)
GSON은 중첩 클래스를 쉽게 직렬화하고 정적 중첩 클래스를 실시 할 수 있습니다. 내부 클래스의 매개 변수가없는 생성자는 그것을 포함하는 객체 (즉, 외부 클래스의 인스턴스)를 참조해야하기 때문에 GSON은 순수한 내부 클래스를 자동으로 손질 할 수 없습니다. 정적 클래스를 제조하기 위해 내부 클래스를 정적으로 또는 사용자 정의 인스턴스 제작자를 제공 할 수 있습니다. 예는 다음과 같습니다.
공개 클래스 A {공개 문자열 a; 클래스 B {공개 문자열 B; public b () {// b}}}}}}}}위의 클래스 B는 GSON에 의해 직렬화 될 수 없습니다. 클래스 B는 (정적) 내부 클래스이므로 GSON은 또한 클래스 B 인스턴스로 { "b": "abc"}를 사로화 할 수 없습니다.
또 다른 해결책은 b에 대한 인스턴스 제작자를 작성하는 것입니다.
공개 클래스 InstanceCreatorForb instanceCreator <ab> {private final a a; public instancecreatorforb (a) {this.a = a; } public ab createInstance (유형 유형) {return a.new b (); }}이 방법은 실현 가능하지만 권장되지 않습니다. (번역가는이 인스턴스 제작자를 이해하지 못하고 사용 방법을 몰랐다고 말했습니다)
예 : 배열
gson gson = new gson (); int [] ints = {1, 2, 3, 4, 5}; String [] strings = { "abc", "def", "ghi"}; // serializationgson.tojson (ints); ==> 인쇄 [1,2,3,4,5] gson.tojson (문자열); ==> prints [ "abc", "def", "ghi"] // deserializationint [] ints2 = gson.fromjson ( "[1,2,3,4,5]", int []. class); ==> ints2는 ints와 동일합니다.GSON은 또한 복잡한 데이터 유형의 다차원 배열을 지원합니다.
예 : 수집
gson gson = new gson (); 수집 <integer> ints = lists.immutablelist (1,2,3,4,5); // serializationstring json = gson.tojson (ints); // ==> JSON은 [1,2,3,4,5] // DeserializationType CollectionType = New TypEtoken <integer >> () {{}. getType (); collection <integer> ints2 = gson.fromjson (json, collectionType); // ints2는 ints와 동일합니다.컬렉션을 처리 할 때의 제한 :
제네릭을 직렬화/사형화합니다
TOJSON (OBJ)을 사용할 때 GSON은 OBJ.getClass ()를 호출하여 직렬화에 사용하기위한 필드 정보를 얻습니다. 마찬가지로, 객체 MyClass.class는 객체가 일반적인 것이 아닌 경우 사용할 수있는 json (json, myclass.class) 메소드로 매개 변수로 전달 될 수 있습니다. 그러나 객체가 일반 유형 객체 인 경우 Java의 유형 삭제 메커니즘으로 인해 일반 유형 정보가 손실됩니다. 다음 예는 다음을 보여줍니다.
클래스 foo <t> {t value;} gson gson = new gson (); foo <bar> foo = new foo <bar> (); gson.tojson (foo); // foo.value rightlygson.fromjson (json, foo.getclass ()); // foo. value를 막대로 삼키지 못합니다위의 코드는 값을 막대 유형으로 해석합니다. gson은 클래스의 정보를 얻기 위해 foo.getclass ()를 호출하지만이 메소드는 기본 클래스, 즉 foo.class를 반환합니다. 이것은 GSON이 이것이 foo <bar> 유형의 대상이라는 것을 알 수 없음을 의미합니다.
이 문제를 해결하려면 제네릭에 대한 올바른 매개 변수화 유형을 지정할 수 있습니다. TypEtoken 클래스를 사용할 수 있습니다.
type footype = new TypEtoken <foo <bar >> () {} .getType (); gson.tojson (foo, footype); gson.fromjson (json, footype);Footype는 실제로 모든 매개 변수화 된 유형을 반환 할 수있는 gettype () 메소드가 포함 된 익명의 내부 클래스를 정의합니다.
모든 유형의 객체 모음을 직렬화/사형화하십시오
때때로 처리 된 JSON에는 다음과 같은 혼합 유형이 포함됩니다.
[ 'hello', 5, {이름 : '인사', 출처 : '게스트'}]해당 세트는 다음과 같습니다.
Collection Collection = New ArrayList (); Collection.Add ( "Hello"); Collection.Add (5); Collection.Add (New Event ( "Greetings", "Guest"));
이벤트 클래스는 다음과 같이 정의됩니다.
클래스 이벤트 {개인 문자열 이름; 개인 문자열 소스; 비공개 이벤트 (문자열 이름, 문자열 소스) {this.name = 이름; this.source = source; }}GSON을 사용하면 컬렉션을 연속화하기 위해 특별한 작업을 수행 할 필요가 없습니다. Tojson (Collection)은 만족스러운 결과를 출력합니다.
그러나 GSON은 JSON의 내용에 해당 할 수 없기 때문에 FromJson (JSON, Collection.Class)을 통한 사산화는 불가능합니다. GSON은 FromJson의 수집 유형의 공통 버전을 제공해야합니다. 세 가지 선택이 있습니다.
솔루션 1 : GSON PARSER의 API (저수준 스트림 파서 또는 DOM 파서 JSONPARSER)를 사용하여 배열 요소를 구문 분석 한 다음 GSON.fromjson ()을 사용하여 각 배열 요소를 처리하십시오. 이것은 선호되는 솔루션입니다.
반응식 2 : Collection.class에 대한 유형 어댑터를 배열의 요소를 적절한 개체에 매핑하는 데 등록하십시오. 이 방법의 단점은 다른 컬렉션 유형을 다룰 때 불편을 일으킬 것입니다.
반응식 3 : MyCollectionMemberType에 대한 유형 어댑터를 등록하고 Fromjson에서 <MyCollectionMemberType>을 사용하십시오. 이 메소드는 배열이 높은 수준의 요소처럼 보이거나 필드 유형을 수집으로 변경할 수있는 경우에만 가능합니다.
내장 세리어 라이저/사제
GSON은 기본 표현에 적합하지 않을 수있는 일반적으로 사용되는 클래스에 대한 SERIALIZER/DESERIALIZER를 제공합니다.
다음은 이러한 수업 목록입니다.
맞춤형 직렬화/사제화
때로는 GSON의 기본 구현은 원하는 것이 아니며 일부 클래스 라이브러리 (예 : DateTime)를 처리 할 때 더 일반적입니다.
GSON을 사용하면 사용자 정의 직렬화/사막화기를 등록 할 수 있습니다. 이렇게하려면 다음 부분을 구현해야합니다.
JSON 시리얼 라이저 : 객체의 직렬화를 사용자 정의해야합니다
JSON DESERIALIZER : 유형에 대한 사막화 클래스 제작자를 사용자 정의해야합니다. 매개 변수가없는 생성자 또는 사막화 제가 등록 된 경우 필요하지 않습니다.
GSONBUILDER GSON = NEW GSONBUILDER (); gson.registertyPeadapter (myType2.class, new myTypeadapter ()); gson.registertypeadapter (mytype.class, new mySerializer ()); gson.regittertypeadapter (mytype.class, new myDeserializer ()); gson.registertypeadapter (mytype.class, new myinstanceCreator ());
RegisterTyPeadapter 유형 어댑터가 여러 인터페이스를 구현하고 이러한 인터페이스의 유형 어댑터를 등록하는지 확인합니다.
시리얼 라이저를 작성하십시오
다음은 DateTime의 Serializer를 사용자 정의하는 예입니다.
Private Class DateTimeserializer는 jsonserializer <dateTime>을 구현합니다. {public jsonlement serialize (datetime src, type type typeofsrc, jsonserializationcontext context) {return new jsonprimitive (src.tostring ()); }}GSON은 dateTime 인스턴스를 일련의 시리얼화 할 때 tojson ()을 호출합니다.
사제를 작성하십시오
다음 예제는 DateTime 클래스의 사제를 작성하는 방법을 보여줍니다.
Private Class DateTimedEserializer는 JSONDESERIALIZER <DATETIME> {public dateMe deserialize (jsonElement JSON, Type TypeOft, jsondeserializationContext Context) jsonParseException {return new DateTime (json.getasjsonPrimitive (). getAsString ()); }}GSON이 JSON 문자열을 DATETIME 객체로 삼아야 할 때, json ()가 호출됩니다.
직렬화/사막화제의 경우 다음에주의를 기울여야합니다.
인스턴스 제작자를 작성하십시오
객체를 제조 할 때 GSON은 클래스 인스턴스를 만들어야합니다. 직렬화/사제화 중에 잘 수행되는 클래스는이 클래스에 매개 변수가없는 생성자가 있음을 의미합니다. 일반적으로 클래스 라이브러리에서 매개 변수가없는 생성자가없는 클래스를 처리 할 때 인스턴스 제작자가 필요합니다.
제작자 예제 예 :
개인 클래스 MoneyinstanceCreator는 InstanceCreator <money> {공공 자금 CreateInstance (유형 유형) {return new Money ( "10000000", CurrencyCode.usd); }}매개 변수화 유형 인스턴스 제작자
때로는 인스턴스화 할 유형이 매개 변수화 된 유형입니다. 전반적으로 실제 인스턴스는 원시 유형이므로 문제가되지 않습니다. 예는 다음과 같습니다.
Class MyList <T>는 ArrayList <T> {} Class MyListInstanCecreator instanceCreator <MyList <? >> {@SuppressWarnings ( "Checked") 공개 MyList <?> 실제 인스턴스가 원시 유형을 가질 수 있기 때문에 매개 변수 목록을 사용할 필요가 없습니다. 새로운 mylist ()를 반환합니다. }}그러나 때로는 실제 매개 변수화 된 유형을 기반으로 인스턴스를 만들어야합니다. 이 경우 유형 매개 변수를 CreateInstance 메소드로 전달할 수 있습니다. 예는 다음과 같습니다.
공개 클래스 ID <t> {개인 최종 클래스 <T> classOfid; 개인 최종 긴 가치; public id (class <t> classofid, long value) {this.classofid = classofid; this.value = value; }} class idinstanceCreator는 instanceCreator <id <? >> {public id <?> createinstance (유형 유형) {type [] typeparameters = ((ParameterizedType) type) .getActualTyPearguments (); 유형 idtype = typeparameters [0]; // id는 하나의 매개 변수화 된 type t return id.get ((class) idtype, 0l) 만 있습니다. }}위의 예에서는 실제 유형을 매개 변수화 된 유형으로 전달하지 않고도 ID 클래스의 인스턴스를 만들 수 없습니다. 매개 변수 유형을 메소드에 전달 하여이 문제를 해결할 수 있습니다. 여기서, 유형 객체는 Java 매개 변수화 된 유형의 id <foo>의 표현으로 간주 될 수 있으며, 해당 인스턴스는 id <foo>에 바인딩되어야합니다. 클래스 ID는 매개 변수의 하나만 가지고 있으므로 getActualTyPearGument ()를 사용 하여이 예에서는 유형 배열의 0 번째 요소를 반환합니다. foo.class.
소형 출력 대 아름다운 출력
GSON에서 JSON의 기본 출력은 Compact JSON 형식입니다. 즉, JSON에는 여분의 공백 문자가 없습니다. 따라서 필드 이름과 필드 값, 필드 사이 및 JSON 출력의 배열 요소 사이에 빈 공간이 없습니다. 또한 NULL 필드는 출력되지 않습니다 (참고 : NULL은 수집 및 배열 객체에 보존됩니다).
더 아름답게 출력하려면 GSONBUILDER를 사용하여 GSON 인스턴스를 구성해야합니다. JSONFormatter는 공개 API에 존재하지 않으므로 클라이언트는 기본 출력 설정을 구성 할 수 없습니다. 이제 우리는 기본적으로 라인 당 80 자일 JSONPRINTFORMATTE만을 제공하며, 들여 쓰기는 2 문자를 사용하고 오른쪽 여백은 4 자입니다.
다음 예제는 기본 jsoncompactformatter를 사용하는 대신 jsonprintformatter를 사용하기 위해 GSON 인스턴스를 가져 오는 방법을 보여줍니다.
GSON GSON = NEW GSONBUILDER (). SETPRETTYPRINTING (). create (); String jsonOutput = gson.tojson (someObject);
빈 개체
GSON의 기본 구현에서 NULL 객체는 무시됩니다. 이로 인해 출력 형식 (직렬화 결과로 간주 될 수 있음)이 더 엄격해질 수 있습니다. 그러나 클라이언트는 JSON이 정상적으로 사로화 할 수 있도록 기본값을 정의해야합니다.
GSON 인스턴스 직렬화 가능한 null을 만들려면 다음을 수행 할 수 있습니다.
GSON GSON = NEW GSONBUILDER (). serializenulls (). create ();
NULL 직렬화 할 때 JSONNULL 요소가 JSONELEMENT 구조에 추가됩니다. 따라서 사용자 정의 시리얼 라이저/사막화기 에서이 객체 (GSON)를 사용할 수 있습니다.
예는 다음과 같습니다.
공개 클래스 foo {개인 최종 문자열 s; 개인 최종 INT I; public foo () {this (null, 5); } public foo (문자열 s, int i) {this.s = s; this.i = i; }} gson = new GsonBuilder (). serializenulls (). create (); foo foo = new foo (); String json = gson.tojson (foo); system.out.println (json);산출:
{ "s": null, "i": 5} null버전 지원
@Since 주석을 사용하여 동일한 객체의 여러 버전을 유지할 수 있습니다. 이 주석은 클래스와 필드에서 사용될 수 있으며 향후 방법에 따라 지원됩니다. 이 기능을 사용하려면 특정 버전 번호보다 큰 필드 및 객체를 무시하려면 GSON 인스턴스를 구성해야합니다. 버전이 GSON 객체에 설정되지 않은 경우 모든 필드와 클래스는 직렬화/사제화 할 때 사용됩니다.
Public Class versionedClass {@since (1.1) Private Final String Newerfield; @Since (1.0) Private Final String Newfield; 개인 최종 문자열 필드; public versionedClass () {this.newerfield = "newer"; this.newfield = "new"; this.field = "old"; }} versionedClass versionedObject = new versionedClass (); gson gson = new GsonBuilder (). setVersion (1.0) .create (); String JsonOutput = gson.tojson (someObject); system.out.out.println (jsonoutput); jsonoutput); gson.tojson (someObject); system.out.println (jsonoutput);산출:
{ "Newfield": "New", "Field": "Old"} { "Newerfield": "Newer", "Newfield": "New", "Field": "Old"}직렬화/사막화에서 필드를 제외합니다
GSON은 클래스, 필드 및 필드 유형을 제거하기 위해 많은 방법을 사용하는 것을 지원합니다. 다음 방법이 귀하의 요구를 충족하지 않으면 사용자 정리/사막화 방법을 사용할 수 있습니다.
1. 자바 수정 자 제외
기본적으로 필드가 과도로 선언되면 필드는 제외됩니다. 또한 필드가 정적으로 선언되면이 필드는 기본적으로 제외됩니다. 일시적으로 선언 된 일부 필드를 포함하려면 다음을 수행 할 수 있습니다.
import java.lang.reflect.modifier; gson gson = new GsonBuilder () .excludeFieldsWithModifiers (modifier.static) .create ();
ExcludeFieldsWithModifiers 메소드에서 가능한 한 많은 수정 자 상수를 사용할 수 있습니다. 예를 들어:
GSON GSON = NEW GSONBUILDER () .excludeFieldsWithModifiers (modifier.static, modifier.transient, modifier.volatile) .create ();
2. @Expose 필드를 사용하여 제외하십시오
이 기능을 사용하면 클래스에서 특정 필드를 태그하여 직렬화/사막화에서 제외/제외되지 않도록합니다. 이 주석을 사용하려면 새로운 gsonBuilder ()를 사용하여 GSON을 작성해야합니다. GSON 인스턴스는 @expose로 표시되지 않은 클래스의 모든 필드를 제외합니다.
3. 사용자 정의 제외 정책
위의 제외 방법이 요구 사항을 충족 할 수없는 경우 제외 전략을 사용자 정의 할 수도 있습니다. 자세한 내용은 ExclusionStrategy Javadoc을 참조하십시오.
다음 예제는 @foo로 표시된 필드를 제외하고 최상위 유형의 문자열 클래스 또는 선언 된 필드 유형을 제외하는 방법을 보여줍니다.
@retention (rendentionpolicy.runtime) @target ({ElementType.field}) public @Interface foo {// 필드 태그 전용 주석} public class sampleObjectfortest {@foo private final int annotatedfield; 개인 최종 문자열 Stringfield; 개인 최종 Long Longfield; 개인 최종 클래스 <?> Clazzfield; public sampleObjectfortest () {annotatedfield = 5; Stringfield = "SomedeFaultValue"; Longfield = 1234; }} public class myExclusionStrategy는 제외 시설 스트레이트가 {private final class <?> typetoskip; private myexclusionstrategy (class <?> typetoskip) {this.typetoskip = typetoskip; } public boolean rookskipclass (class <?> clazz) {return (clazz == typetoskip); } public boolean rookskipfield (FieldAttributes f) {return f.getAntotation (foo.class)! = null; }} public static void main (string [] args) {gson gson = new GsonBuilder () .SetExClusionStrategies (new MyExclusionStrategy (String.class)) .serializenulls () .create (); SampleObjectfortest SRC = 새로운 SampleObjectfortest (); 문자열 json = gson.tojson (src); System.out.println (JSON); }산출:
{ "Longfield": 1234}JSON 필드 이름 지정 지원
GSON의 사전 정의 된 필드 명명 전략은 표준 Java 필드 이름 (즉, SampleFieldNameInjava와 같은 Camel Nomenclature)을 JSON 필드 이름 (Sample_Field_name_in_java 또는 SampleFieldNameInjava)으로 변환 할 수 있습니다. 자세한 내용은 FieldNamingPolicy를 참조하십시오.
GSON은 또한 클라이언트가 필드 이름을 사용자 정의 할 수 있도록 주석 기반 정책을 가지고 있습니다. 이 전략에 따라 불법 필드 이름이 주석이 달린 값으로 제공되는 경우 GSON은 런타임 예외를 던집니다.
다음 예는이 두 GSON 명명 전략을 사용하는 방법을 보여줍니다.
개인 클래스 someObject {@serializedname ( "Custom_naming") 비공개 최종 문자열 몇 가지 필드; 비공개 최종 문자열 일부 서 필드; public someObject (String a, String b) {this.somefield = a; this.someotherfield = b; }} someObject sodobject = new soverbject ( "First", "Second"); gson gson = new GsonBuilder (). SetfieldNamingPolicy (FieldNamingPolicy.upper_camel_case) .create (); String jsonRepresentation = gson.tojson (someObject); system.out.prsintln (jsonrepresentation);산출:
{ "custom_naming": "First", "someotherfield": "Second"}}이름을 사용자 정의하려면 @SerializedName 주석을 사용할 수 있습니다.
직렬 라이저와 사제 간의 상태를 공유합니다
때로는 시리얼 라이저와 디스 세 리아 라이저간에 상태를 공유해야하며 다음 세 가지 방법을 사용하여 목표를 달성 할 수 있습니다.
처음 두 가지 방법은 스레드 안전이 아니고 세 번째 방법은입니다.
GSON 구문 분석 NULL 오류에 대한 해결책
GSON의 단점 중 하나는 NULL 교체를 설정할 수 없다는 것입니다.
서버에서 반환 한 널을 배치로 수동으로 교체 할 수 있습니다. 일반 인터페이스가 정의되면 서버는 확실히 NULL을 반환 할 수 없지만 배경 결과는 항상 NULL로 나타납니다!
검색하면 일반적인 대답이 있습니다.
GSON GSON = NEW GSONBUILDER (). serializenulls (). create ();
그러나 이것은 Desequence 문제를 해결할 수 없으며 어떻게 해결 하는가?
솔루션은 다음과 같습니다.
GSON GSON = NEW GSONBUILDER (). RegisterTyPeadApterFactory (NEW NULLSTRINGTOEMPTYADAPTERFACTORY (). nullStringToEmptyAdApterFactory <T>는 typeadApterFactory {@suppresswarnings ( "선택 취소") public <t> typeadapter <t> create (gson gson, typetoken <t> type) {class <t> rawtype = (class <t>) type.getRawtype (); if (rawtype! = string.class) {return null; } return (typeadapter <T>) 새 StringNullAdapter (); }} // StringNullAdapter 코드 public class stringNullAdapter는 typeadapter <string> {@override public string read (jsonreader reader)를 IoException {// todo auto-regenated method stub if (reader.peek () == jsontoken.null) {reader.nextnull (); 반품 ""; } return reader.nextstring (); } @override public void write (jsonwriter writer, String value)는 ioexception {// todo 자동 생성 메소드 스터브 if (value == null) {writer.nullValue (); 반품; } writer.Value (값); }}