forked from KNEMC/KLALB
增加启动xtcp frpc功能
This commit is contained in:
+32
-53
@@ -1,86 +1,65 @@
|
|||||||
{
|
{
|
||||||
"name" : "KNECloud",
|
"name" : "KNECloud",
|
||||||
"services" : [ {
|
"services" : [ {
|
||||||
"name" : "KNE官网",
|
"name" : "KNE官网",
|
||||||
"protocol" : "HTTP",
|
"protocol" : "HTTP",
|
||||||
"localaddress" : "127.0.0.1:8081"
|
"localaddress" : "127.0.0.1:8081"
|
||||||
}, {
|
}, {
|
||||||
"name" : "KNE云盘",
|
"name" : "KNE云盘",
|
||||||
"protocol" : "HTTP",
|
"protocol" : "HTTP",
|
||||||
"localaddress" : "127.0.0.1:5212"
|
"localaddress" : "127.0.0.1:5212"
|
||||||
}, {
|
}, {
|
||||||
"name" : "服务器远程桌面",
|
"name" : "服务器远程桌面",
|
||||||
"protocol" : "RDP",
|
"protocol" : "RDP",
|
||||||
"localaddress" : "127.0.0.1:3389"
|
"localaddress" : "127.0.0.1:3389"
|
||||||
} ],
|
} ],
|
||||||
"tunnels" : [ {
|
"tunnels" : [ {
|
||||||
"name" : "Openfrp-直连线路",
|
"name" : "Openfrp-直连线路",
|
||||||
"remoteaddress" : "127.0.0.1:4566"
|
"remoteaddress" : "127.0.0.1:4566",
|
||||||
}, {
|
"frpc":[ "[common]",
|
||||||
"name" : "Openfrp-直连线路",
|
"server_addr = 180.76.147.250",
|
||||||
"remoteaddress" : "127.0.0.1:4566"
|
"server_port = 8120",
|
||||||
|
"tcp_mux = true",
|
||||||
|
"protocol = tcp",
|
||||||
|
"dns_server = 223.5.5.5",
|
||||||
|
"user = bb28264e0abf3bcbec3a2180c5a279b8",
|
||||||
|
"token = I2KMo1HvRxuvurv2",
|
||||||
|
"[ts1xx]",
|
||||||
|
"type = xtcp",
|
||||||
|
"role = visitor",
|
||||||
|
"server_name = zl1",
|
||||||
|
"bind_addr = 127.0.0.1",
|
||||||
|
"bind_port = 4566",
|
||||||
|
"sk = knecloud"]
|
||||||
},{
|
},{
|
||||||
"name" : "NULL-宿迁联通",
|
"name" : "NULL-宿迁联通",
|
||||||
"remoteaddress" : "153.36.240.12:65529"
|
"remoteaddress" : "153.36.240.12:65529"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Openfrp-韩国春川-1",
|
"name" : "Openfrp-北京多线-3",
|
||||||
"remoteaddress" : "kr-nc-bgp-1.openfrp.top:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Openfrp-北京多线-3",
|
|
||||||
"remoteaddress" : "cn-bj-bgp-3.openfrp.top:65529"
|
"remoteaddress" : "cn-bj-bgp-3.openfrp.top:65529"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Openfrp-北京多线-7",
|
"name" : "Openfrp-北京多线-7",
|
||||||
"remoteaddress" : "180.76.147.250:65529"
|
"remoteaddress" : "180.76.147.250:65529"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Openfrp-美国-8「BGP」",
|
"name" : "Sakurafrp-安徽电信-1",
|
||||||
"remoteaddress" : "us-los-bgp-8.openfrp.top:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Sakurafrp-安徽电信-1",
|
|
||||||
"remoteaddress" : "cn-ah-dx-1.natfrp.cloud:65529"
|
"remoteaddress" : "cn-ah-dx-1.natfrp.cloud:65529"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Sakurafrp-十堰电信-1",
|
"name" : "Sakurafrp-南宁电信-1",
|
||||||
"remoteaddress" : "cn-sy-dx-1.natfrp.cloud:65529"
|
"remoteaddress" : "cn-nn-dx-1.natfrp.cloud:65529"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Sakurafrp-武汉电信-1",
|
"name" : "Sakurafrp-武汉电信-1",
|
||||||
"remoteaddress" : "cn-wh-dx-1.natfrp.cloud:65529"
|
"remoteaddress" : "cn-wh-dx-1.natfrp.cloud:65529"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Sakurafrp-枣庄BGP-10",
|
"name" : "Sakurafrp-枣庄BGP-10",
|
||||||
"remoteaddress" : "cn-zz-bgp-10.natfrp.cloud:23330"
|
"remoteaddress" : "cn-zz-bgp-10.natfrp.cloud:23330"
|
||||||
}, {
|
}, {
|
||||||
"name" : "Sakurafrp-枣庄BGP-7",
|
"name" : "Sakurafrp-枣庄BGP-7",
|
||||||
"remoteaddress" : "cn-zz-bgp-7.natfrp.cloud:33336"
|
"remoteaddress" : "cn-zz-bgp-7.natfrp.cloud:33336"
|
||||||
}, {
|
}, {
|
||||||
"name" : "HYHBX-深圳阿里-1",
|
"name" : "HYHBX-深圳阿里-1",
|
||||||
"remoteaddress" : "119.23.238.91:12413"
|
"remoteaddress" : "119.23.238.91:12413"
|
||||||
}, {
|
}, {
|
||||||
"name" : "HYHBX-上海腾讯-2",
|
"name" : "HYHBX-上海腾讯-2",
|
||||||
"remoteaddress" : "43.143.109.64:49965"
|
"remoteaddress" : "43.143.109.64:49965"
|
||||||
}, {
|
|
||||||
"name" : "XYZ-韩国首尔",
|
|
||||||
"remoteaddress" : "frp.104300.xyz:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-美国洛杉矶",
|
|
||||||
"remoteaddress" : "la.afrps.cn:49966"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-新加坡",
|
|
||||||
"remoteaddress" : "sg.afrps.cn:49966"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-美国芝加哥",
|
|
||||||
"remoteaddress" : "ch.afrps.cn:49966"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-美国圣何塞",
|
|
||||||
"remoteaddress" : "sj.afrps.cn:49966"
|
|
||||||
} , {
|
|
||||||
"name" : "Freefrp-韩国首尔-0",
|
|
||||||
"remoteaddress" : "frp.freefrp.net:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "Freefrp-韩国首尔-1",
|
|
||||||
"remoteaddress" : "frp1.freefrp.net:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "Freefrp-韩国首尔-2",
|
|
||||||
"remoteaddress" : "frp2.freefrp.net:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "Freefrp-韩国首尔-4",
|
|
||||||
"remoteaddress" : "frp4.freefrp.net:49965"
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|||||||
-86
@@ -1,86 +0,0 @@
|
|||||||
{
|
|
||||||
"name" : "KNECloud",
|
|
||||||
"services" : [ {
|
|
||||||
"name" : "KNE官网",
|
|
||||||
"protocol" : "HTTP",
|
|
||||||
"localaddress" : "127.0.0.1:8081"
|
|
||||||
}, {
|
|
||||||
"name" : "KNE云盘",
|
|
||||||
"protocol" : "HTTP",
|
|
||||||
"localaddress" : "127.0.0.1:5212"
|
|
||||||
}, {
|
|
||||||
"name" : "服务器远程桌面",
|
|
||||||
"protocol" : "RDP",
|
|
||||||
"localaddress" : "127.0.0.1:3389"
|
|
||||||
} ],
|
|
||||||
"tunnels" : [ {
|
|
||||||
"name" : "Openfrp-直连线路",
|
|
||||||
"remoteaddress" : "127.0.0.1:4566"
|
|
||||||
}, {
|
|
||||||
"name" : "Openfrp-直连线路",
|
|
||||||
"remoteaddress" : "127.0.0.1:4566"
|
|
||||||
},{
|
|
||||||
"name" : "NULL-宿迁联通",
|
|
||||||
"remoteaddress" : "153.36.240.12:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Openfrp-韩国春川-1",
|
|
||||||
"remoteaddress" : "kr-nc-bgp-1.openfrp.top:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Openfrp-北京多线-3",
|
|
||||||
"remoteaddress" : "cn-bj-bgp-3.openfrp.top:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Openfrp-北京多线-7",
|
|
||||||
"remoteaddress" : "180.76.147.250:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Openfrp-美国-8「BGP」",
|
|
||||||
"remoteaddress" : "us-los-bgp-8.openfrp.top:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Sakurafrp-安徽电信-1",
|
|
||||||
"remoteaddress" : "cn-ah-dx-1.natfrp.cloud:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Sakurafrp-十堰电信-1",
|
|
||||||
"remoteaddress" : "cn-sy-dx-1.natfrp.cloud:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Sakurafrp-武汉电信-1",
|
|
||||||
"remoteaddress" : "cn-wh-dx-1.natfrp.cloud:65529"
|
|
||||||
}, {
|
|
||||||
"name" : "Sakurafrp-枣庄BGP-10",
|
|
||||||
"remoteaddress" : "cn-zz-bgp-10.natfrp.cloud:23330"
|
|
||||||
}, {
|
|
||||||
"name" : "Sakurafrp-枣庄BGP-7",
|
|
||||||
"remoteaddress" : "cn-zz-bgp-7.natfrp.cloud:33336"
|
|
||||||
}, {
|
|
||||||
"name" : "HYHBX-深圳阿里-1",
|
|
||||||
"remoteaddress" : "119.23.238.91:12413"
|
|
||||||
}, {
|
|
||||||
"name" : "HYHBX-上海腾讯-2",
|
|
||||||
"remoteaddress" : "43.143.109.64:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "XYZ-韩国首尔",
|
|
||||||
"remoteaddress" : "frp.104300.xyz:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-美国洛杉矶",
|
|
||||||
"remoteaddress" : "la.afrps.cn:49966"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-新加坡",
|
|
||||||
"remoteaddress" : "sg.afrps.cn:49966"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-美国芝加哥",
|
|
||||||
"remoteaddress" : "ch.afrps.cn:49966"
|
|
||||||
}, {
|
|
||||||
"name" : "aFrps-美国圣何塞",
|
|
||||||
"remoteaddress" : "sj.afrps.cn:49966"
|
|
||||||
} , {
|
|
||||||
"name" : "Freefrp-韩国首尔-0",
|
|
||||||
"remoteaddress" : "frp.freefrp.net:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "Freefrp-韩国首尔-1",
|
|
||||||
"remoteaddress" : "frp1.freefrp.net:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "Freefrp-韩国首尔-2",
|
|
||||||
"remoteaddress" : "frp2.freefrp.net:49965"
|
|
||||||
}, {
|
|
||||||
"name" : "Freefrp-韩国首尔-4",
|
|
||||||
"remoteaddress" : "frp4.freefrp.net:49965"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name" : "KNECloud",
|
||||||
|
"services" : [ {
|
||||||
|
"name" : "KNE官网",
|
||||||
|
"protocol" : "HTTP",
|
||||||
|
"localaddress" : "127.0.0.1:8081"
|
||||||
|
}, {
|
||||||
|
"name" : "KNE云盘",
|
||||||
|
"protocol" : "HTTP",
|
||||||
|
"localaddress" : "127.0.0.1:5212"
|
||||||
|
}, {
|
||||||
|
"name" : "服务器远程桌面",
|
||||||
|
"protocol" : "RDP",
|
||||||
|
"localaddress" : "127.0.0.1:3389"
|
||||||
|
} ],
|
||||||
|
"tunnels" : [ {
|
||||||
|
"name" : "Openfrp-韩国春川-1",
|
||||||
|
"remoteaddress" : "kr-nc-bgp-1.openfrp.top:65529"
|
||||||
|
}, {
|
||||||
|
"name" : "Openfrp-北京多线-3",
|
||||||
|
"remoteaddress" : "cn-bj-bgp-3.openfrp.top:65529"
|
||||||
|
}, {
|
||||||
|
"name" : "Openfrp-北京多线-7",
|
||||||
|
"remoteaddress" : "180.76.147.250:65529"
|
||||||
|
}, {
|
||||||
|
"name" : "Openfrp-美国-8「BGP」",
|
||||||
|
"remoteaddress" : "us-los-bgp-8.openfrp.top:65529"
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -1,119 +1,119 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This type adapter supports three subclasses of date: Date, Timestamp, and
|
* This type adapter supports three subclasses of date: Date, Timestamp, and
|
||||||
* java.sql.Date.
|
* java.sql.Date.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
|
final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
|
||||||
|
|
||||||
// TODO: migrate to streaming adapter
|
// TODO: migrate to streaming adapter
|
||||||
|
|
||||||
private final DateFormat enUsFormat;
|
private final DateFormat enUsFormat;
|
||||||
private final DateFormat localFormat;
|
private final DateFormat localFormat;
|
||||||
private final DateFormat iso8601Format;
|
private final DateFormat iso8601Format;
|
||||||
|
|
||||||
DefaultDateTypeAdapter() {
|
DefaultDateTypeAdapter() {
|
||||||
this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US),
|
this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US),
|
||||||
DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
|
DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultDateTypeAdapter(String datePattern) {
|
DefaultDateTypeAdapter(String datePattern) {
|
||||||
this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern));
|
this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultDateTypeAdapter(int style) {
|
DefaultDateTypeAdapter(int style) {
|
||||||
this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style));
|
this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
|
public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
|
||||||
this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US),
|
this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US),
|
||||||
DateFormat.getDateTimeInstance(dateStyle, timeStyle));
|
DateFormat.getDateTimeInstance(dateStyle, timeStyle));
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) {
|
DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) {
|
||||||
this.enUsFormat = enUsFormat;
|
this.enUsFormat = enUsFormat;
|
||||||
this.localFormat = localFormat;
|
this.localFormat = localFormat;
|
||||||
this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||||
this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// These methods need to be synchronized since JDK DateFormat classes are not thread-safe
|
// These methods need to be synchronized since JDK DateFormat classes are not thread-safe
|
||||||
// See issue 162
|
// See issue 162
|
||||||
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
|
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
synchronized (localFormat) {
|
synchronized (localFormat) {
|
||||||
String dateFormatAsString = enUsFormat.format(src);
|
String dateFormatAsString = enUsFormat.format(src);
|
||||||
return new JsonPrimitive(dateFormatAsString);
|
return new JsonPrimitive(dateFormatAsString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
throws JsonParseException {
|
throws JsonParseException {
|
||||||
if (!(json instanceof JsonPrimitive)) {
|
if (!(json instanceof JsonPrimitive)) {
|
||||||
throw new JsonParseException("The date should be a string value");
|
throw new JsonParseException("The date should be a string value");
|
||||||
}
|
}
|
||||||
Date date = deserializeToDate(json);
|
Date date = deserializeToDate(json);
|
||||||
if (typeOfT == Date.class) {
|
if (typeOfT == Date.class) {
|
||||||
return date;
|
return date;
|
||||||
} else if (typeOfT == Timestamp.class) {
|
} else if (typeOfT == Timestamp.class) {
|
||||||
return new Timestamp(date.getTime());
|
return new Timestamp(date.getTime());
|
||||||
} else if (typeOfT == java.sql.Date.class) {
|
} else if (typeOfT == java.sql.Date.class) {
|
||||||
return new java.sql.Date(date.getTime());
|
return new java.sql.Date(date.getTime());
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT);
|
throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date deserializeToDate(JsonElement json) {
|
private Date deserializeToDate(JsonElement json) {
|
||||||
synchronized (localFormat) {
|
synchronized (localFormat) {
|
||||||
try {
|
try {
|
||||||
return localFormat.parse(json.getAsString());
|
return localFormat.parse(json.getAsString());
|
||||||
} catch (ParseException ignored) {
|
} catch (ParseException ignored) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return enUsFormat.parse(json.getAsString());
|
return enUsFormat.parse(json.getAsString());
|
||||||
} catch (ParseException ignored) {
|
} catch (ParseException ignored) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return iso8601Format.parse(json.getAsString());
|
return iso8601Format.parse(json.getAsString());
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(json.getAsString(), e);
|
throw new JsonSyntaxException(json.getAsString(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(DefaultDateTypeAdapter.class.getSimpleName());
|
sb.append(DefaultDateTypeAdapter.class.getSimpleName());
|
||||||
sb.append('(').append(localFormat.getClass().getSimpleName()).append(')');
|
sb.append('(').append(localFormat.getClass().getSimpleName()).append(')');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +1,109 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
|
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
|
||||||
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
|
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
|
||||||
* if the {@link #shouldSkipClass(Class)} method returns false then that class or field type
|
* if the {@link #shouldSkipClass(Class)} method returns false then that class or field type
|
||||||
* will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
|
* will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
|
||||||
* returns false, then it will not be set as part of the Java object structure.
|
* returns false, then it will not be set as part of the Java object structure.
|
||||||
*
|
*
|
||||||
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
|
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
|
||||||
*
|
*
|
||||||
* <p><strong>Exclude fields and objects based on a particular class type:</strong>
|
* <p><strong>Exclude fields and objects based on a particular class type:</strong>
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
|
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
|
||||||
* private final Class<?> excludedThisClass;
|
* private final Class<?> excludedThisClass;
|
||||||
*
|
*
|
||||||
* public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
|
* public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
|
||||||
* this.excludedThisClass = excludedThisClass;
|
* this.excludedThisClass = excludedThisClass;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public boolean shouldSkipClass(Class<?> clazz) {
|
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
* return excludedThisClass.equals(clazz);
|
* return excludedThisClass.equals(clazz);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public boolean shouldSkipField(FieldAttributes f) {
|
* public boolean shouldSkipField(FieldAttributes f) {
|
||||||
* return excludedThisClass.equals(f.getDeclaredClass());
|
* return excludedThisClass.equals(f.getDeclaredClass());
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
|
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* public @interface FooAnnotation {
|
* public @interface FooAnnotation {
|
||||||
* // some implementation here
|
* // some implementation here
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* // Excludes any field (or class) that is tagged with an "@FooAnnotation"
|
* // Excludes any field (or class) that is tagged with an "@FooAnnotation"
|
||||||
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
|
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
|
||||||
* public boolean shouldSkipClass(Class<?> clazz) {
|
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||||
* return clazz.getAnnotation(FooAnnotation.class) != null;
|
* return clazz.getAnnotation(FooAnnotation.class) != null;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public boolean shouldSkipField(FieldAttributes f) {
|
* public boolean shouldSkipField(FieldAttributes f) {
|
||||||
* return f.getAnnotation(FooAnnotation.class) != null;
|
* return f.getAnnotation(FooAnnotation.class) != null;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
|
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
|
||||||
* the {@code GsonBuilder} is required. The following is an example of how you can use the
|
* the {@code GsonBuilder} is required. The following is an example of how you can use the
|
||||||
* {@code GsonBuilder} to configure Gson to use one of the above sample:
|
* {@code GsonBuilder} to configure Gson to use one of the above sample:
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||||
* Gson gson = new GsonBuilder()
|
* Gson gson = new GsonBuilder()
|
||||||
* .setExclusionStrategies(excludeStrings)
|
* .setExclusionStrategies(excludeStrings)
|
||||||
* .create();
|
* .create();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>For certain model classes, you may only want to serialize a field, but exclude it for
|
* <p>For certain model classes, you may only want to serialize a field, but exclude it for
|
||||||
* deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal;
|
* deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal;
|
||||||
* however, you would register it with the
|
* however, you would register it with the
|
||||||
* {@link GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)} method.
|
* {@link GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)} method.
|
||||||
* For example:
|
* For example:
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||||
* Gson gson = new GsonBuilder()
|
* Gson gson = new GsonBuilder()
|
||||||
* .addDeserializationExclusionStrategy(excludeStrings)
|
* .addDeserializationExclusionStrategy(excludeStrings)
|
||||||
* .create();
|
* .create();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*
|
*
|
||||||
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
|
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
|
||||||
* @see GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)
|
* @see GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)
|
||||||
* @see GsonBuilder#addSerializationExclusionStrategy(ExclusionStrategy)
|
* @see GsonBuilder#addSerializationExclusionStrategy(ExclusionStrategy)
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public interface ExclusionStrategy {
|
public interface ExclusionStrategy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param f the field object that is under test
|
* @param f the field object that is under test
|
||||||
* @return true if the field should be ignored; otherwise false
|
* @return true if the field should be ignored; otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean shouldSkipField(FieldAttributes f);
|
public boolean shouldSkipField(FieldAttributes f);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param clazz the class object that is under test
|
* @param clazz the class object that is under test
|
||||||
* @return true if the class should be ignored; otherwise false
|
* @return true if the class should be ignored; otherwise false
|
||||||
*/
|
*/
|
||||||
public boolean shouldSkipClass(Class<?> clazz);
|
public boolean shouldSkipClass(Class<?> clazz);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,157 +1,157 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Google Inc.
|
* Copyright (C) 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data object that stores attributes of a field.
|
* A data object that stores attributes of a field.
|
||||||
*
|
*
|
||||||
* <p>This class is immutable; therefore, it can be safely shared across threads.
|
* <p>This class is immutable; therefore, it can be safely shared across threads.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public final class FieldAttributes {
|
public final class FieldAttributes {
|
||||||
private final Field field;
|
private final Field field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a Field Attributes object from the {@code f}.
|
* Constructs a Field Attributes object from the {@code f}.
|
||||||
*
|
*
|
||||||
* @param f the field to pull attributes from
|
* @param f the field to pull attributes from
|
||||||
*/
|
*/
|
||||||
public FieldAttributes(Field f) {
|
public FieldAttributes(Field f) {
|
||||||
$Gson$Preconditions.checkNotNull(f);
|
$Gson$Preconditions.checkNotNull(f);
|
||||||
this.field = f;
|
this.field = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the declaring class that contains this field
|
* @return the declaring class that contains this field
|
||||||
*/
|
*/
|
||||||
public Class<?> getDeclaringClass() {
|
public Class<?> getDeclaringClass() {
|
||||||
return field.getDeclaringClass();
|
return field.getDeclaringClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the name of the field
|
* @return the name of the field
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return field.getName();
|
return field.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>For example, assume the following class definition:
|
* <p>For example, assume the following class definition:
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* public class Foo {
|
* public class Foo {
|
||||||
* private String bar;
|
* private String bar;
|
||||||
* private List<String> red;
|
* private List<String> red;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
|
* Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>This method would return {@code String.class} for the {@code bar} field and
|
* <p>This method would return {@code String.class} for the {@code bar} field and
|
||||||
* {@code listParameterizedType} for the {@code red} field.
|
* {@code listParameterizedType} for the {@code red} field.
|
||||||
*
|
*
|
||||||
* @return the specific type declared for this field
|
* @return the specific type declared for this field
|
||||||
*/
|
*/
|
||||||
public Type getDeclaredType() {
|
public Type getDeclaredType() {
|
||||||
return field.getGenericType();
|
return field.getGenericType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@code Class} object that was declared for this field.
|
* Returns the {@code Class} object that was declared for this field.
|
||||||
*
|
*
|
||||||
* <p>For example, assume the following class definition:
|
* <p>For example, assume the following class definition:
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* public class Foo {
|
* public class Foo {
|
||||||
* private String bar;
|
* private String bar;
|
||||||
* private List<String> red;
|
* private List<String> red;
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>This method would return {@code String.class} for the {@code bar} field and
|
* <p>This method would return {@code String.class} for the {@code bar} field and
|
||||||
* {@code List.class} for the {@code red} field.
|
* {@code List.class} for the {@code red} field.
|
||||||
*
|
*
|
||||||
* @return the specific class object that was declared for the field
|
* @return the specific class object that was declared for the field
|
||||||
*/
|
*/
|
||||||
public Class<?> getDeclaredClass() {
|
public Class<?> getDeclaredClass() {
|
||||||
return field.getType();
|
return field.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@code T} annotation object from this field if it exist; otherwise returns
|
* Return the {@code T} annotation object from this field if it exist; otherwise returns
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
*
|
*
|
||||||
* @param annotation the class of the annotation that will be retrieved
|
* @param annotation the class of the annotation that will be retrieved
|
||||||
* @return the annotation instance if it is bound to the field; otherwise {@code null}
|
* @return the annotation instance if it is bound to the field; otherwise {@code null}
|
||||||
*/
|
*/
|
||||||
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
|
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
|
||||||
return field.getAnnotation(annotation);
|
return field.getAnnotation(annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the annotations that are present on this field.
|
* Return the annotations that are present on this field.
|
||||||
*
|
*
|
||||||
* @return an array of all the annotations set on the field
|
* @return an array of all the annotations set on the field
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public Collection<Annotation> getAnnotations() {
|
public Collection<Annotation> getAnnotations() {
|
||||||
return Arrays.asList(field.getAnnotations());
|
return Arrays.asList(field.getAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if the field is defined with the {@code modifier}.
|
* Returns {@code true} if the field is defined with the {@code modifier}.
|
||||||
*
|
*
|
||||||
* <p>This method is meant to be called as:
|
* <p>This method is meant to be called as:
|
||||||
* <pre class="code">
|
* <pre class="code">
|
||||||
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
|
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @see java.lang.reflect.Modifier
|
* @see java.lang.reflect.Modifier
|
||||||
*/
|
*/
|
||||||
public boolean hasModifier(int modifier) {
|
public boolean hasModifier(int modifier) {
|
||||||
return (field.getModifiers() & modifier) != 0;
|
return (field.getModifiers() & modifier) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||||
*
|
*
|
||||||
* @return true if the field is synthetic; otherwise false
|
* @return true if the field is synthetic; otherwise false
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
*/
|
*/
|
||||||
Object get(Object instance) throws IllegalAccessException {
|
Object get(Object instance) throws IllegalAccessException {
|
||||||
return field.get(instance);
|
return field.get(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
* This is exposed internally only for the removing synthetic fields from the JSON output.
|
||||||
*
|
*
|
||||||
* @return true if the field is synthetic; otherwise false
|
* @return true if the field is synthetic; otherwise false
|
||||||
*/
|
*/
|
||||||
boolean isSynthetic() {
|
boolean isSynthetic() {
|
||||||
return field.isSynthetic();
|
return field.isSynthetic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,168 +1,168 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enumeration that defines a few standard naming conventions for JSON field names.
|
* An enumeration that defines a few standard naming conventions for JSON field names.
|
||||||
* This enumeration should be used in conjunction with {@link com.google.gson.GsonBuilder}
|
* This enumeration should be used in conjunction with {@link com.google.gson.GsonBuilder}
|
||||||
* to configure a {@link com.google.gson.Gson} instance to properly translate Java field
|
* to configure a {@link com.google.gson.Gson} instance to properly translate Java field
|
||||||
* names into the desired JSON field names.
|
* names into the desired JSON field names.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public enum FieldNamingPolicy implements FieldNamingStrategy {
|
public enum FieldNamingPolicy implements FieldNamingStrategy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using this naming policy with Gson will ensure that the field name is
|
* Using this naming policy with Gson will ensure that the field name is
|
||||||
* unchanged.
|
* unchanged.
|
||||||
*/
|
*/
|
||||||
IDENTITY() {
|
IDENTITY() {
|
||||||
public String translateName(Field f) {
|
public String translateName(Field f) {
|
||||||
return f.getName();
|
return f.getName();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using this naming policy with Gson will ensure that the first "letter" of the Java
|
* Using this naming policy with Gson will ensure that the first "letter" of the Java
|
||||||
* field name is capitalized when serialized to its JSON form.
|
* field name is capitalized when serialized to its JSON form.
|
||||||
*
|
*
|
||||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>someFieldName ---> SomeFieldName</li>
|
* <li>someFieldName ---> SomeFieldName</li>
|
||||||
* <li>_someFieldName ---> _SomeFieldName</li>
|
* <li>_someFieldName ---> _SomeFieldName</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
UPPER_CAMEL_CASE() {
|
UPPER_CAMEL_CASE() {
|
||||||
public String translateName(Field f) {
|
public String translateName(Field f) {
|
||||||
return upperCaseFirstLetter(f.getName());
|
return upperCaseFirstLetter(f.getName());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using this naming policy with Gson will ensure that the first "letter" of the Java
|
* Using this naming policy with Gson will ensure that the first "letter" of the Java
|
||||||
* field name is capitalized when serialized to its JSON form and the words will be
|
* field name is capitalized when serialized to its JSON form and the words will be
|
||||||
* separated by a space.
|
* separated by a space.
|
||||||
*
|
*
|
||||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>someFieldName ---> Some Field Name</li>
|
* <li>someFieldName ---> Some Field Name</li>
|
||||||
* <li>_someFieldName ---> _Some Field Name</li>
|
* <li>_someFieldName ---> _Some Field Name</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
UPPER_CAMEL_CASE_WITH_SPACES() {
|
UPPER_CAMEL_CASE_WITH_SPACES() {
|
||||||
public String translateName(Field f) {
|
public String translateName(Field f) {
|
||||||
return upperCaseFirstLetter(separateCamelCase(f.getName(), " "));
|
return upperCaseFirstLetter(separateCamelCase(f.getName(), " "));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using this naming policy with Gson will modify the Java Field name from its camel cased
|
* Using this naming policy with Gson will modify the Java Field name from its camel cased
|
||||||
* form to a lower case field name where each word is separated by an underscore (_).
|
* form to a lower case field name where each word is separated by an underscore (_).
|
||||||
*
|
*
|
||||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>someFieldName ---> some_field_name</li>
|
* <li>someFieldName ---> some_field_name</li>
|
||||||
* <li>_someFieldName ---> _some_field_name</li>
|
* <li>_someFieldName ---> _some_field_name</li>
|
||||||
* <li>aStringField ---> a_string_field</li>
|
* <li>aStringField ---> a_string_field</li>
|
||||||
* <li>aURL ---> a_u_r_l</li>
|
* <li>aURL ---> a_u_r_l</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
LOWER_CASE_WITH_UNDERSCORES() {
|
LOWER_CASE_WITH_UNDERSCORES() {
|
||||||
public String translateName(Field f) {
|
public String translateName(Field f) {
|
||||||
return separateCamelCase(f.getName(), "_").toLowerCase();
|
return separateCamelCase(f.getName(), "_").toLowerCase();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using this naming policy with Gson will modify the Java Field name from its camel cased
|
* Using this naming policy with Gson will modify the Java Field name from its camel cased
|
||||||
* form to a lower case field name where each word is separated by a dash (-).
|
* form to a lower case field name where each word is separated by a dash (-).
|
||||||
*
|
*
|
||||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>someFieldName ---> some-field-name</li>
|
* <li>someFieldName ---> some-field-name</li>
|
||||||
* <li>_someFieldName ---> _some-field-name</li>
|
* <li>_someFieldName ---> _some-field-name</li>
|
||||||
* <li>aStringField ---> a-string-field</li>
|
* <li>aStringField ---> a-string-field</li>
|
||||||
* <li>aURL ---> a-u-r-l</li>
|
* <li>aURL ---> a-u-r-l</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
|
* Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
|
||||||
* expressions. This requires that a field named with dashes is always accessed as a quoted
|
* expressions. This requires that a field named with dashes is always accessed as a quoted
|
||||||
* property like {@code myobject['my-field']}. Accessing it as an object field
|
* property like {@code myobject['my-field']}. Accessing it as an object field
|
||||||
* {@code myobject.my-field} will result in an unintended javascript expression.
|
* {@code myobject.my-field} will result in an unintended javascript expression.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
LOWER_CASE_WITH_DASHES() {
|
LOWER_CASE_WITH_DASHES() {
|
||||||
public String translateName(Field f) {
|
public String translateName(Field f) {
|
||||||
return separateCamelCase(f.getName(), "-").toLowerCase();
|
return separateCamelCase(f.getName(), "-").toLowerCase();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the field name that uses camel-case define word separation into
|
* Converts the field name that uses camel-case define word separation into
|
||||||
* separate words that are separated by the provided {@code separatorString}.
|
* separate words that are separated by the provided {@code separatorString}.
|
||||||
*/
|
*/
|
||||||
private static String separateCamelCase(String name, String separator) {
|
private static String separateCamelCase(String name, String separator) {
|
||||||
StringBuilder translation = new StringBuilder();
|
StringBuilder translation = new StringBuilder();
|
||||||
for (int i = 0; i < name.length(); i++) {
|
for (int i = 0; i < name.length(); i++) {
|
||||||
char character = name.charAt(i);
|
char character = name.charAt(i);
|
||||||
if (Character.isUpperCase(character) && translation.length() != 0) {
|
if (Character.isUpperCase(character) && translation.length() != 0) {
|
||||||
translation.append(separator);
|
translation.append(separator);
|
||||||
}
|
}
|
||||||
translation.append(character);
|
translation.append(character);
|
||||||
}
|
}
|
||||||
return translation.toString();
|
return translation.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures the JSON field names begins with an upper case letter.
|
* Ensures the JSON field names begins with an upper case letter.
|
||||||
*/
|
*/
|
||||||
private static String upperCaseFirstLetter(String name) {
|
private static String upperCaseFirstLetter(String name) {
|
||||||
StringBuilder fieldNameBuilder = new StringBuilder();
|
StringBuilder fieldNameBuilder = new StringBuilder();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
char firstCharacter = name.charAt(index);
|
char firstCharacter = name.charAt(index);
|
||||||
|
|
||||||
while (index < name.length() - 1) {
|
while (index < name.length() - 1) {
|
||||||
if (Character.isLetter(firstCharacter)) {
|
if (Character.isLetter(firstCharacter)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldNameBuilder.append(firstCharacter);
|
fieldNameBuilder.append(firstCharacter);
|
||||||
firstCharacter = name.charAt(++index);
|
firstCharacter = name.charAt(++index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == name.length()) {
|
if (index == name.length()) {
|
||||||
return fieldNameBuilder.toString();
|
return fieldNameBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Character.isUpperCase(firstCharacter)) {
|
if (!Character.isUpperCase(firstCharacter)) {
|
||||||
String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index);
|
String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index);
|
||||||
return fieldNameBuilder.append(modifiedTarget).toString();
|
return fieldNameBuilder.append(modifiedTarget).toString();
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) {
|
private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) {
|
||||||
return (indexOfSubstring < srcString.length())
|
return (indexOfSubstring < srcString.length())
|
||||||
? firstCharacter + srcString.substring(indexOfSubstring)
|
? firstCharacter + srcString.substring(indexOfSubstring)
|
||||||
: String.valueOf(firstCharacter);
|
: String.valueOf(firstCharacter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
|
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
|
||||||
* field names into a particular convention that is not supported as a normal Java field
|
* field names into a particular convention that is not supported as a normal Java field
|
||||||
* declaration rules. For example, Java does not support "-" characters in a field name.
|
* declaration rules. For example, Java does not support "-" characters in a field name.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public interface FieldNamingStrategy {
|
public interface FieldNamingStrategy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the field name into its JSON field name representation.
|
* Translates the field name into its JSON field name representation.
|
||||||
*
|
*
|
||||||
* @param f the field object that we are translating
|
* @param f the field object that we are translating
|
||||||
* @return the translated field name.
|
* @return the translated field name.
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public String translateName(Field f);
|
public String translateName(Field f);
|
||||||
}
|
}
|
||||||
|
|||||||
+856
-856
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,92 +1,92 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is implemented to create instances of a class that does not define a no-args
|
* This interface is implemented to create instances of a class that does not define a no-args
|
||||||
* constructor. If you can modify the class, you should instead add a private, or public
|
* constructor. If you can modify the class, you should instead add a private, or public
|
||||||
* no-args constructor. However, that is not possible for library classes, such as JDK classes, or
|
* no-args constructor. However, that is not possible for library classes, such as JDK classes, or
|
||||||
* a third-party library that you do not have source-code of. In such cases, you should define an
|
* a third-party library that you do not have source-code of. In such cases, you should define an
|
||||||
* instance creator for the class. Implementations of this interface should be registered with
|
* instance creator for the class. Implementations of this interface should be registered with
|
||||||
* {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use
|
* {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use
|
||||||
* them.
|
* them.
|
||||||
* <p>Let us look at an example where defining an InstanceCreator might be useful. The
|
* <p>Let us look at an example where defining an InstanceCreator might be useful. The
|
||||||
* {@code Id} class defined below does not have a default no-args constructor.</p>
|
* {@code Id} class defined below does not have a default no-args constructor.</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class Id<T> {
|
* public class Id<T> {
|
||||||
* private final Class<T> clazz;
|
* private final Class<T> clazz;
|
||||||
* private final long value;
|
* private final long value;
|
||||||
* public Id(Class<T> clazz, long value) {
|
* public Id(Class<T> clazz, long value) {
|
||||||
* this.clazz = clazz;
|
* this.clazz = clazz;
|
||||||
* this.value = value;
|
* this.value = value;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>If Gson encounters an object of type {@code Id} during deserialization, it will throw an
|
* <p>If Gson encounters an object of type {@code Id} during deserialization, it will throw an
|
||||||
* exception. The easiest way to solve this problem will be to add a (public or private) no-args
|
* exception. The easiest way to solve this problem will be to add a (public or private) no-args
|
||||||
* constructor as follows:</p>
|
* constructor as follows:</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* private Id() {
|
* private Id() {
|
||||||
* this(Object.class, 0L);
|
* this(Object.class, 0L);
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>However, let us assume that the developer does not have access to the source-code of the
|
* <p>However, let us assume that the developer does not have access to the source-code of the
|
||||||
* {@code Id} class, or does not want to define a no-args constructor for it. The developer
|
* {@code Id} class, or does not want to define a no-args constructor for it. The developer
|
||||||
* can solve this problem by defining an {@code InstanceCreator} for {@code Id}:</p>
|
* can solve this problem by defining an {@code InstanceCreator} for {@code Id}:</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* class IdInstanceCreator implements InstanceCreator<Id> {
|
* class IdInstanceCreator implements InstanceCreator<Id> {
|
||||||
* public Id createInstance(Type type) {
|
* public Id createInstance(Type type) {
|
||||||
* return new Id(Object.class, 0L);
|
* return new Id(Object.class, 0L);
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>Note that it does not matter what the fields of the created instance contain since Gson will
|
* <p>Note that it does not matter what the fields of the created instance contain since Gson will
|
||||||
* overwrite them with the deserialized values specified in Json. You should also ensure that a
|
* overwrite them with the deserialized values specified in Json. You should also ensure that a
|
||||||
* <i>new</i> object is returned, not a common object since its fields will be overwritten.
|
* <i>new</i> object is returned, not a common object since its fields will be overwritten.
|
||||||
* The developer will need to register {@code IdInstanceCreator} with Gson as follows:</p>
|
* The developer will need to register {@code IdInstanceCreator} with Gson as follows:</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
|
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param <T> the type of object that will be created by this implementation.
|
* @param <T> the type of object that will be created by this implementation.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public interface InstanceCreator<T> {
|
public interface InstanceCreator<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gson invokes this call-back method during deserialization to create an instance of the
|
* Gson invokes this call-back method during deserialization to create an instance of the
|
||||||
* specified type. The fields of the returned instance are overwritten with the data present
|
* specified type. The fields of the returned instance are overwritten with the data present
|
||||||
* in the Json. Since the prior contents of the object are destroyed and overwritten, do not
|
* in the Json. Since the prior contents of the object are destroyed and overwritten, do not
|
||||||
* return an instance that is useful elsewhere. In particular, do not return a common instance,
|
* return an instance that is useful elsewhere. In particular, do not return a common instance,
|
||||||
* always use {@code new} to create a new instance.
|
* always use {@code new} to create a new instance.
|
||||||
*
|
*
|
||||||
* @param type the parameterized T represented as a {@link Type}.
|
* @param type the parameterized T represented as a {@link Type}.
|
||||||
* @return a default object instance of type T.
|
* @return a default object instance of type T.
|
||||||
*/
|
*/
|
||||||
public T createInstance(Type type);
|
public T createInstance(Type type);
|
||||||
}
|
}
|
||||||
|
|||||||
+282
-282
@@ -1,282 +1,282 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class representing an array type in Json. An array is a list of {@link JsonElement}s each of
|
* A class representing an array type in Json. An array is a list of {@link JsonElement}s each of
|
||||||
* which can be of a different type. This is an ordered list, meaning that the order in which
|
* which can be of a different type. This is an ordered list, meaning that the order in which
|
||||||
* elements are added is preserved.
|
* elements are added is preserved.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
|
public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
|
||||||
private final List<JsonElement> elements;
|
private final List<JsonElement> elements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty JsonArray.
|
* Creates an empty JsonArray.
|
||||||
*/
|
*/
|
||||||
public JsonArray() {
|
public JsonArray() {
|
||||||
elements = new ArrayList<JsonElement>();
|
elements = new ArrayList<JsonElement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the specified element to self.
|
* Adds the specified element to self.
|
||||||
*
|
*
|
||||||
* @param element the element that needs to be added to the array.
|
* @param element the element that needs to be added to the array.
|
||||||
*/
|
*/
|
||||||
public void add(JsonElement element) {
|
public void add(JsonElement element) {
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
element = JsonNull.INSTANCE;
|
element = JsonNull.INSTANCE;
|
||||||
}
|
}
|
||||||
elements.add(element);
|
elements.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds all the elements of the specified array to self.
|
* Adds all the elements of the specified array to self.
|
||||||
*
|
*
|
||||||
* @param array the array whose elements need to be added to the array.
|
* @param array the array whose elements need to be added to the array.
|
||||||
*/
|
*/
|
||||||
public void addAll(JsonArray array) {
|
public void addAll(JsonArray array) {
|
||||||
elements.addAll(array.elements);
|
elements.addAll(array.elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of elements in the array.
|
* Returns the number of elements in the array.
|
||||||
*
|
*
|
||||||
* @return the number of elements in the array.
|
* @return the number of elements in the array.
|
||||||
*/
|
*/
|
||||||
public int size() {
|
public int size() {
|
||||||
return elements.size();
|
return elements.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator to navigate the elemetns of the array. Since the array is an ordered list,
|
* Returns an iterator to navigate the elemetns of the array. Since the array is an ordered list,
|
||||||
* the iterator navigates the elements in the order they were inserted.
|
* the iterator navigates the elements in the order they were inserted.
|
||||||
*
|
*
|
||||||
* @return an iterator to navigate the elements of the array.
|
* @return an iterator to navigate the elements of the array.
|
||||||
*/
|
*/
|
||||||
public Iterator<JsonElement> iterator() {
|
public Iterator<JsonElement> iterator() {
|
||||||
return elements.iterator();
|
return elements.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ith element of the array.
|
* Returns the ith element of the array.
|
||||||
*
|
*
|
||||||
* @param i the index of the element that is being sought.
|
* @param i the index of the element that is being sought.
|
||||||
* @return the element present at the ith index.
|
* @return the element present at the ith index.
|
||||||
* @throws IndexOutOfBoundsException if i is negative or greater than or equal to the
|
* @throws IndexOutOfBoundsException if i is negative or greater than or equal to the
|
||||||
* {@link #size()} of the array.
|
* {@link #size()} of the array.
|
||||||
*/
|
*/
|
||||||
public JsonElement get(int i) {
|
public JsonElement get(int i) {
|
||||||
return elements.get(i);
|
return elements.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a {@link Number} if it contains a single element.
|
* convenience method to get this array as a {@link Number} if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a number if it is single element array.
|
* @return get this element as a number if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid Number.
|
* is not a valid Number.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Number getAsNumber() {
|
public Number getAsNumber() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsNumber();
|
return elements.get(0).getAsNumber();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a {@link String} if it contains a single element.
|
* convenience method to get this array as a {@link String} if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a String if it is single element array.
|
* @return get this element as a String if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid String.
|
* is not a valid String.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getAsString() {
|
public String getAsString() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsString();
|
return elements.get(0).getAsString();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a double if it contains a single element.
|
* convenience method to get this array as a double if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a double if it is single element array.
|
* @return get this element as a double if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid double.
|
* is not a valid double.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double getAsDouble() {
|
public double getAsDouble() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsDouble();
|
return elements.get(0).getAsDouble();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a {@link BigDecimal} if it contains a single element.
|
* convenience method to get this array as a {@link BigDecimal} if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link BigDecimal} if it is single element array.
|
* @return get this element as a {@link BigDecimal} if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
|
||||||
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}.
|
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getAsBigDecimal() {
|
public BigDecimal getAsBigDecimal() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsBigDecimal();
|
return elements.get(0).getAsBigDecimal();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a {@link BigInteger} if it contains a single element.
|
* convenience method to get this array as a {@link BigInteger} if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link BigInteger} if it is single element array.
|
* @return get this element as a {@link BigInteger} if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
|
||||||
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}.
|
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BigInteger getAsBigInteger() {
|
public BigInteger getAsBigInteger() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsBigInteger();
|
return elements.get(0).getAsBigInteger();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a float if it contains a single element.
|
* convenience method to get this array as a float if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a float if it is single element array.
|
* @return get this element as a float if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid float.
|
* is not a valid float.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public float getAsFloat() {
|
public float getAsFloat() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsFloat();
|
return elements.get(0).getAsFloat();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a long if it contains a single element.
|
* convenience method to get this array as a long if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a long if it is single element array.
|
* @return get this element as a long if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid long.
|
* is not a valid long.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long getAsLong() {
|
public long getAsLong() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsLong();
|
return elements.get(0).getAsLong();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as an integer if it contains a single element.
|
* convenience method to get this array as an integer if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as an integer if it is single element array.
|
* @return get this element as an integer if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid integer.
|
* is not a valid integer.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getAsInt() {
|
public int getAsInt() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsInt();
|
return elements.get(0).getAsInt();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getAsByte() {
|
public byte getAsByte() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsByte();
|
return elements.get(0).getAsByte();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getAsCharacter() {
|
public char getAsCharacter() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsCharacter();
|
return elements.get(0).getAsCharacter();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a primitive short if it contains a single element.
|
* convenience method to get this array as a primitive short if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive short if it is single element array.
|
* @return get this element as a primitive short if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid short.
|
* is not a valid short.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public short getAsShort() {
|
public short getAsShort() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsShort();
|
return elements.get(0).getAsShort();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this array as a boolean if it contains a single element.
|
* convenience method to get this array as a boolean if it contains a single element.
|
||||||
*
|
*
|
||||||
* @return get this element as a boolean if it is single element array.
|
* @return get this element as a boolean if it is single element array.
|
||||||
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
|
||||||
* is not a valid boolean.
|
* is not a valid boolean.
|
||||||
* @throws IllegalStateException if the array has more than one element.
|
* @throws IllegalStateException if the array has more than one element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean getAsBoolean() {
|
public boolean getAsBoolean() {
|
||||||
if (elements.size() == 1) {
|
if (elements.size() == 1) {
|
||||||
return elements.get(0).getAsBoolean();
|
return elements.get(0).getAsBoolean();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements));
|
return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return elements.hashCode();
|
return elements.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for deserialization that is passed to a custom deserializer during invocation of its
|
* Context for deserialization that is passed to a custom deserializer during invocation of its
|
||||||
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)}
|
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)}
|
||||||
* method.
|
* method.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public interface JsonDeserializationContext {
|
public interface JsonDeserializationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes default deserialization on the specified object. It should never be invoked on
|
* Invokes default deserialization on the specified object. It should never be invoked on
|
||||||
* the element received as a parameter of the
|
* the element received as a parameter of the
|
||||||
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing
|
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing
|
||||||
* so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
|
* so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
|
||||||
*
|
*
|
||||||
* @param json the parse tree.
|
* @param json the parse tree.
|
||||||
* @param typeOfT type of the expected return value.
|
* @param typeOfT type of the expected return value.
|
||||||
* @param <T> The type of the deserialized object.
|
* @param <T> The type of the deserialized object.
|
||||||
* @return An object of type typeOfT.
|
* @return An object of type typeOfT.
|
||||||
* @throws JsonParseException if the parse tree does not contain expected data.
|
* @throws JsonParseException if the parse tree does not contain expected data.
|
||||||
*/
|
*/
|
||||||
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
|
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +1,91 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Interface representing a custom deserializer for Json. You should write a custom
|
* <p>Interface representing a custom deserializer for Json. You should write a custom
|
||||||
* deserializer, if you are not happy with the default deserialization done by Gson. You will
|
* deserializer, if you are not happy with the default deserialization done by Gson. You will
|
||||||
* also need to register this deserializer through
|
* also need to register this deserializer through
|
||||||
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}.</p>
|
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}.</p>
|
||||||
*
|
*
|
||||||
* <p>Let us look at example where defining a deserializer will be useful. The {@code Id} class
|
* <p>Let us look at example where defining a deserializer will be useful. The {@code Id} class
|
||||||
* defined below has two fields: {@code clazz} and {@code value}.</p>
|
* defined below has two fields: {@code clazz} and {@code value}.</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class Id<T> {
|
* public class Id<T> {
|
||||||
* private final Class<T> clazz;
|
* private final Class<T> clazz;
|
||||||
* private final long value;
|
* private final long value;
|
||||||
* public Id(Class<T> clazz, long value) {
|
* public Id(Class<T> clazz, long value) {
|
||||||
* this.clazz = clazz;
|
* this.clazz = clazz;
|
||||||
* this.value = value;
|
* this.value = value;
|
||||||
* }
|
* }
|
||||||
* public long getValue() {
|
* public long getValue() {
|
||||||
* return value;
|
* return value;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
|
* <p>The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
|
||||||
* Json string to be <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you already know
|
* Json string to be <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you already know
|
||||||
* the type of the field that the {@code Id} will be deserialized into, and hence just want to
|
* the type of the field that the {@code Id} will be deserialized into, and hence just want to
|
||||||
* deserialize it from a Json string {@code 20}. You can achieve that by writing a custom
|
* deserialize it from a Json string {@code 20}. You can achieve that by writing a custom
|
||||||
* deserializer:</p>
|
* deserializer:</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* class IdDeserializer implements JsonDeserializer<Id>() {
|
* class IdDeserializer implements JsonDeserializer<Id>() {
|
||||||
* public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
* public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
* throws JsonParseException {
|
* throws JsonParseException {
|
||||||
* return new Id((Class)typeOfT, id.getValue());
|
* return new Id((Class)typeOfT, id.getValue());
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>You will also need to register {@code IdDeserializer} with Gson as follows:</p>
|
* <p>You will also need to register {@code IdDeserializer} with Gson as follows:</p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
|
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
|
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
|
||||||
* is more efficient than this interface's tree API.
|
* is more efficient than this interface's tree API.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*
|
*
|
||||||
* @param <T> type for which the deserializer is being registered. It is possible that a
|
* @param <T> type for which the deserializer is being registered. It is possible that a
|
||||||
* deserializer may be asked to deserialize a specific generic type of the T.
|
* deserializer may be asked to deserialize a specific generic type of the T.
|
||||||
*/
|
*/
|
||||||
public interface JsonDeserializer<T> {
|
public interface JsonDeserializer<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gson invokes this call-back method during deserialization when it encounters a field of the
|
* Gson invokes this call-back method during deserialization when it encounters a field of the
|
||||||
* specified type.
|
* specified type.
|
||||||
* <p>In the implementation of this call-back method, you should consider invoking
|
* <p>In the implementation of this call-back method, you should consider invoking
|
||||||
* {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects
|
* {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects
|
||||||
* for any non-trivial field of the returned object. However, you should never invoke it on the
|
* for any non-trivial field of the returned object. However, you should never invoke it on the
|
||||||
* the same type passing {@code json} since that will cause an infinite loop (Gson will call your
|
* the same type passing {@code json} since that will cause an infinite loop (Gson will call your
|
||||||
* call-back method again).
|
* call-back method again).
|
||||||
*
|
*
|
||||||
* @param json The Json data being deserialized
|
* @param json The Json data being deserialized
|
||||||
* @param typeOfT The type of the Object to deserialize to
|
* @param typeOfT The type of the Object to deserialize to
|
||||||
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
|
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
|
||||||
* @throws JsonParseException if json is not in the expected format of {@code typeofT}
|
* @throws JsonParseException if json is not in the expected format of {@code typeofT}
|
||||||
*/
|
*/
|
||||||
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
throws JsonParseException;
|
throws JsonParseException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,324 +1,324 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.internal.Streams;
|
import com.google.gson.internal.Streams;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class representing an element of Json. It could either be a {@link JsonObject}, a
|
* A class representing an element of Json. It could either be a {@link JsonObject}, a
|
||||||
* {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}.
|
* {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public abstract class JsonElement {
|
public abstract class JsonElement {
|
||||||
/**
|
/**
|
||||||
* provides check for verifying if this element is an array or not.
|
* provides check for verifying if this element is an array or not.
|
||||||
*
|
*
|
||||||
* @return true if this element is of type {@link JsonArray}, false otherwise.
|
* @return true if this element is of type {@link JsonArray}, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isJsonArray() {
|
public boolean isJsonArray() {
|
||||||
return this instanceof JsonArray;
|
return this instanceof JsonArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* provides check for verifying if this element is a Json object or not.
|
* provides check for verifying if this element is a Json object or not.
|
||||||
*
|
*
|
||||||
* @return true if this element is of type {@link JsonObject}, false otherwise.
|
* @return true if this element is of type {@link JsonObject}, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isJsonObject() {
|
public boolean isJsonObject() {
|
||||||
return this instanceof JsonObject;
|
return this instanceof JsonObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* provides check for verifying if this element is a primitive or not.
|
* provides check for verifying if this element is a primitive or not.
|
||||||
*
|
*
|
||||||
* @return true if this element is of type {@link JsonPrimitive}, false otherwise.
|
* @return true if this element is of type {@link JsonPrimitive}, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isJsonPrimitive() {
|
public boolean isJsonPrimitive() {
|
||||||
return this instanceof JsonPrimitive;
|
return this instanceof JsonPrimitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* provides check for verifying if this element represents a null value or not.
|
* provides check for verifying if this element represents a null value or not.
|
||||||
*
|
*
|
||||||
* @return true if this element is of type {@link JsonNull}, false otherwise.
|
* @return true if this element is of type {@link JsonNull}, false otherwise.
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public boolean isJsonNull() {
|
public boolean isJsonNull() {
|
||||||
return this instanceof JsonNull;
|
return this instanceof JsonNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link JsonObject}. If the element is of some
|
* convenience method to get this element as a {@link JsonObject}. If the element is of some
|
||||||
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
||||||
* after ensuring that this element is of the desired type by calling {@link #isJsonObject()}
|
* after ensuring that this element is of the desired type by calling {@link #isJsonObject()}
|
||||||
* first.
|
* first.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link JsonObject}.
|
* @return get this element as a {@link JsonObject}.
|
||||||
* @throws IllegalStateException if the element is of another type.
|
* @throws IllegalStateException if the element is of another type.
|
||||||
*/
|
*/
|
||||||
public JsonObject getAsJsonObject() {
|
public JsonObject getAsJsonObject() {
|
||||||
if (isJsonObject()) {
|
if (isJsonObject()) {
|
||||||
return (JsonObject) this;
|
return (JsonObject) this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Not a JSON Object: " + this);
|
throw new IllegalStateException("Not a JSON Object: " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link JsonArray}. If the element is of some
|
* convenience method to get this element as a {@link JsonArray}. If the element is of some
|
||||||
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
||||||
* after ensuring that this element is of the desired type by calling {@link #isJsonArray()}
|
* after ensuring that this element is of the desired type by calling {@link #isJsonArray()}
|
||||||
* first.
|
* first.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link JsonArray}.
|
* @return get this element as a {@link JsonArray}.
|
||||||
* @throws IllegalStateException if the element is of another type.
|
* @throws IllegalStateException if the element is of another type.
|
||||||
*/
|
*/
|
||||||
public JsonArray getAsJsonArray() {
|
public JsonArray getAsJsonArray() {
|
||||||
if (isJsonArray()) {
|
if (isJsonArray()) {
|
||||||
return (JsonArray) this;
|
return (JsonArray) this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("This is not a JSON Array.");
|
throw new IllegalStateException("This is not a JSON Array.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link JsonPrimitive}. If the element is of some
|
* convenience method to get this element as a {@link JsonPrimitive}. If the element is of some
|
||||||
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
||||||
* after ensuring that this element is of the desired type by calling {@link #isJsonPrimitive()}
|
* after ensuring that this element is of the desired type by calling {@link #isJsonPrimitive()}
|
||||||
* first.
|
* first.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link JsonPrimitive}.
|
* @return get this element as a {@link JsonPrimitive}.
|
||||||
* @throws IllegalStateException if the element is of another type.
|
* @throws IllegalStateException if the element is of another type.
|
||||||
*/
|
*/
|
||||||
public JsonPrimitive getAsJsonPrimitive() {
|
public JsonPrimitive getAsJsonPrimitive() {
|
||||||
if (isJsonPrimitive()) {
|
if (isJsonPrimitive()) {
|
||||||
return (JsonPrimitive) this;
|
return (JsonPrimitive) this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("This is not a JSON Primitive.");
|
throw new IllegalStateException("This is not a JSON Primitive.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link JsonNull}. If the element is of some
|
* convenience method to get this element as a {@link JsonNull}. If the element is of some
|
||||||
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
|
||||||
* after ensuring that this element is of the desired type by calling {@link #isJsonNull()}
|
* after ensuring that this element is of the desired type by calling {@link #isJsonNull()}
|
||||||
* first.
|
* first.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link JsonNull}.
|
* @return get this element as a {@link JsonNull}.
|
||||||
* @throws IllegalStateException if the element is of another type.
|
* @throws IllegalStateException if the element is of another type.
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public JsonNull getAsJsonNull() {
|
public JsonNull getAsJsonNull() {
|
||||||
if (isJsonNull()) {
|
if (isJsonNull()) {
|
||||||
return (JsonNull) this;
|
return (JsonNull) this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("This is not a JSON Null.");
|
throw new IllegalStateException("This is not a JSON Null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a boolean value.
|
* convenience method to get this element as a boolean value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive boolean value.
|
* @return get this element as a primitive boolean value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* boolean value.
|
* boolean value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public boolean getAsBoolean() {
|
public boolean getAsBoolean() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link Boolean} value.
|
* convenience method to get this element as a {@link Boolean} value.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link Boolean} value.
|
* @return get this element as a {@link Boolean} value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* boolean value.
|
* boolean value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
Boolean getAsBooleanWrapper() {
|
Boolean getAsBooleanWrapper() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link Number}.
|
* convenience method to get this element as a {@link Number}.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link Number}.
|
* @return get this element as a {@link Number}.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* number.
|
* number.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public Number getAsNumber() {
|
public Number getAsNumber() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a string value.
|
* convenience method to get this element as a string value.
|
||||||
*
|
*
|
||||||
* @return get this element as a string value.
|
* @return get this element as a string value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* string value.
|
* string value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public String getAsString() {
|
public String getAsString() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive double value.
|
* convenience method to get this element as a primitive double value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive double value.
|
* @return get this element as a primitive double value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* double value.
|
* double value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public double getAsDouble() {
|
public double getAsDouble() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive float value.
|
* convenience method to get this element as a primitive float value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive float value.
|
* @return get this element as a primitive float value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* float value.
|
* float value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public float getAsFloat() {
|
public float getAsFloat() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive long value.
|
* convenience method to get this element as a primitive long value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive long value.
|
* @return get this element as a primitive long value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* long value.
|
* long value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public long getAsLong() {
|
public long getAsLong() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive integer value.
|
* convenience method to get this element as a primitive integer value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive integer value.
|
* @return get this element as a primitive integer value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* integer value.
|
* integer value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public int getAsInt() {
|
public int getAsInt() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive byte value.
|
* convenience method to get this element as a primitive byte value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive byte value.
|
* @return get this element as a primitive byte value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* byte value.
|
* byte value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public byte getAsByte() {
|
public byte getAsByte() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive character value.
|
* convenience method to get this element as a primitive character value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive char value.
|
* @return get this element as a primitive char value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* char value.
|
* char value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public char getAsCharacter() {
|
public char getAsCharacter() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link BigDecimal}.
|
* convenience method to get this element as a {@link BigDecimal}.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link BigDecimal}.
|
* @return get this element as a {@link BigDecimal}.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
|
||||||
* * @throws NumberFormatException if the element is not a valid {@link BigDecimal}.
|
* * @throws NumberFormatException if the element is not a valid {@link BigDecimal}.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public BigDecimal getAsBigDecimal() {
|
public BigDecimal getAsBigDecimal() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link BigInteger}.
|
* convenience method to get this element as a {@link BigInteger}.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link BigInteger}.
|
* @return get this element as a {@link BigInteger}.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
|
||||||
* @throws NumberFormatException if the element is not a valid {@link BigInteger}.
|
* @throws NumberFormatException if the element is not a valid {@link BigInteger}.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public BigInteger getAsBigInteger() {
|
public BigInteger getAsBigInteger() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive short value.
|
* convenience method to get this element as a primitive short value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive short value.
|
* @return get this element as a primitive short value.
|
||||||
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
|
||||||
* short value.
|
* short value.
|
||||||
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
|
||||||
* more than a single element.
|
* more than a single element.
|
||||||
*/
|
*/
|
||||||
public short getAsShort() {
|
public short getAsShort() {
|
||||||
throw new UnsupportedOperationException(getClass().getSimpleName());
|
throw new UnsupportedOperationException(getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a String representation of this element.
|
* Returns a String representation of this element.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
try {
|
try {
|
||||||
StringWriter stringWriter = new StringWriter();
|
StringWriter stringWriter = new StringWriter();
|
||||||
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
JsonWriter jsonWriter = new JsonWriter(stringWriter);
|
||||||
jsonWriter.setLenient(true);
|
jsonWriter.setLenient(true);
|
||||||
Streams.write(this, jsonWriter);
|
Streams.write(this, jsonWriter);
|
||||||
return stringWriter.toString();
|
return stringWriter.toString();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,45 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception is raised when Gson was unable to read an input stream
|
* This exception is raised when Gson was unable to read an input stream
|
||||||
* or write to one.
|
* or write to one.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class JsonIOException extends JsonParseException {
|
public final class JsonIOException extends JsonParseException {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public JsonIOException(String msg) {
|
public JsonIOException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonIOException(String msg, Throwable cause) {
|
public JsonIOException(String msg, Throwable cause) {
|
||||||
super(msg, cause);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates exception with the specified cause. Consider using
|
* Creates exception with the specified cause. Consider using
|
||||||
* {@link #JsonIOException(String, Throwable)} instead if you can describe what happened.
|
* {@link #JsonIOException(String, Throwable)} instead if you can describe what happened.
|
||||||
*
|
*
|
||||||
* @param cause root exception that caused this exception to be thrown.
|
* @param cause root exception that caused this exception to be thrown.
|
||||||
*/
|
*/
|
||||||
public JsonIOException(Throwable cause) {
|
public JsonIOException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+199
-199
@@ -1,199 +1,199 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class representing an object type in Json. An object consists of name-value pairs where names
|
* A class representing an object type in Json. An object consists of name-value pairs where names
|
||||||
* are strings, and values are any other type of {@link JsonElement}. This allows for a creating a
|
* are strings, and values are any other type of {@link JsonElement}. This allows for a creating a
|
||||||
* tree of JsonElements. The member elements of this object are maintained in order they were added.
|
* tree of JsonElements. The member elements of this object are maintained in order they were added.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class JsonObject extends JsonElement {
|
public final class JsonObject extends JsonElement {
|
||||||
// We are using a linked hash map because it is important to preserve
|
// We are using a linked hash map because it is important to preserve
|
||||||
// the order in which elements are inserted. This is needed to ensure
|
// the order in which elements are inserted. This is needed to ensure
|
||||||
// that the fields of an object are inserted in the order they were
|
// that the fields of an object are inserted in the order they were
|
||||||
// defined in the class.
|
// defined in the class.
|
||||||
private final Map<String, JsonElement> members = new LinkedHashMap<String, JsonElement>();
|
private final Map<String, JsonElement> members = new LinkedHashMap<String, JsonElement>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty JsonObject.
|
* Creates an empty JsonObject.
|
||||||
*/
|
*/
|
||||||
public JsonObject() {
|
public JsonObject() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a member, which is a name-value pair, to self. The name must be a String, but the value
|
* Adds a member, which is a name-value pair, to self. The name must be a String, but the value
|
||||||
* can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
|
* can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
|
||||||
* rooted at this node.
|
* rooted at this node.
|
||||||
*
|
*
|
||||||
* @param property name of the member.
|
* @param property name of the member.
|
||||||
* @param value the member object.
|
* @param value the member object.
|
||||||
*/
|
*/
|
||||||
public void add(String property, JsonElement value) {
|
public void add(String property, JsonElement value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = JsonNull.INSTANCE;
|
value = JsonNull.INSTANCE;
|
||||||
}
|
}
|
||||||
members.put($Gson$Preconditions.checkNotNull(property), value);
|
members.put($Gson$Preconditions.checkNotNull(property), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the {@code property} from this {@link JsonObject}.
|
* Removes the {@code property} from this {@link JsonObject}.
|
||||||
*
|
*
|
||||||
* @param property name of the member that should be removed.
|
* @param property name of the member that should be removed.
|
||||||
* @return the {@link JsonElement} object that is being removed.
|
* @return the {@link JsonElement} object that is being removed.
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
public JsonElement remove(String property) {
|
public JsonElement remove(String property) {
|
||||||
return members.remove(property);
|
return members.remove(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to add a primitive member. The specified value is converted to a
|
* Convenience method to add a primitive member. The specified value is converted to a
|
||||||
* JsonPrimitive of String.
|
* JsonPrimitive of String.
|
||||||
*
|
*
|
||||||
* @param property name of the member.
|
* @param property name of the member.
|
||||||
* @param value the string value associated with the member.
|
* @param value the string value associated with the member.
|
||||||
*/
|
*/
|
||||||
public void addProperty(String property, String value) {
|
public void addProperty(String property, String value) {
|
||||||
add(property, createJsonElement(value));
|
add(property, createJsonElement(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to add a primitive member. The specified value is converted to a
|
* Convenience method to add a primitive member. The specified value is converted to a
|
||||||
* JsonPrimitive of Number.
|
* JsonPrimitive of Number.
|
||||||
*
|
*
|
||||||
* @param property name of the member.
|
* @param property name of the member.
|
||||||
* @param value the number value associated with the member.
|
* @param value the number value associated with the member.
|
||||||
*/
|
*/
|
||||||
public void addProperty(String property, Number value) {
|
public void addProperty(String property, Number value) {
|
||||||
add(property, createJsonElement(value));
|
add(property, createJsonElement(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to add a boolean member. The specified value is converted to a
|
* Convenience method to add a boolean member. The specified value is converted to a
|
||||||
* JsonPrimitive of Boolean.
|
* JsonPrimitive of Boolean.
|
||||||
*
|
*
|
||||||
* @param property name of the member.
|
* @param property name of the member.
|
||||||
* @param value the number value associated with the member.
|
* @param value the number value associated with the member.
|
||||||
*/
|
*/
|
||||||
public void addProperty(String property, Boolean value) {
|
public void addProperty(String property, Boolean value) {
|
||||||
add(property, createJsonElement(value));
|
add(property, createJsonElement(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to add a char member. The specified value is converted to a
|
* Convenience method to add a char member. The specified value is converted to a
|
||||||
* JsonPrimitive of Character.
|
* JsonPrimitive of Character.
|
||||||
*
|
*
|
||||||
* @param property name of the member.
|
* @param property name of the member.
|
||||||
* @param value the number value associated with the member.
|
* @param value the number value associated with the member.
|
||||||
*/
|
*/
|
||||||
public void addProperty(String property, Character value) {
|
public void addProperty(String property, Character value) {
|
||||||
add(property, createJsonElement(value));
|
add(property, createJsonElement(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the proper {@link JsonElement} object from the given {@code value} object.
|
* Creates the proper {@link JsonElement} object from the given {@code value} object.
|
||||||
*
|
*
|
||||||
* @param value the object to generate the {@link JsonElement} for
|
* @param value the object to generate the {@link JsonElement} for
|
||||||
* @return a {@link JsonPrimitive} if the {@code value} is not null, otherwise a {@link JsonNull}
|
* @return a {@link JsonPrimitive} if the {@code value} is not null, otherwise a {@link JsonNull}
|
||||||
*/
|
*/
|
||||||
private JsonElement createJsonElement(Object value) {
|
private JsonElement createJsonElement(Object value) {
|
||||||
return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value);
|
return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a set of members of this object. The set is ordered, and the order is in which the
|
* Returns a set of members of this object. The set is ordered, and the order is in which the
|
||||||
* elements were added.
|
* elements were added.
|
||||||
*
|
*
|
||||||
* @return a set of members of this object.
|
* @return a set of members of this object.
|
||||||
*/
|
*/
|
||||||
public Set<Map.Entry<String, JsonElement>> entrySet() {
|
public Set<Map.Entry<String, JsonElement>> entrySet() {
|
||||||
return members.entrySet();
|
return members.entrySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to check if a member with the specified name is present in this object.
|
* Convenience method to check if a member with the specified name is present in this object.
|
||||||
*
|
*
|
||||||
* @param memberName name of the member that is being checked for presence.
|
* @param memberName name of the member that is being checked for presence.
|
||||||
* @return true if there is a member with the specified name, false otherwise.
|
* @return true if there is a member with the specified name, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean has(String memberName) {
|
public boolean has(String memberName) {
|
||||||
return members.containsKey(memberName);
|
return members.containsKey(memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the member with the specified name.
|
* Returns the member with the specified name.
|
||||||
*
|
*
|
||||||
* @param memberName name of the member that is being requested.
|
* @param memberName name of the member that is being requested.
|
||||||
* @return the member matching the name. Null if no such member exists.
|
* @return the member matching the name. Null if no such member exists.
|
||||||
*/
|
*/
|
||||||
public JsonElement get(String memberName) {
|
public JsonElement get(String memberName) {
|
||||||
if (members.containsKey(memberName)) {
|
if (members.containsKey(memberName)) {
|
||||||
JsonElement member = members.get(memberName);
|
JsonElement member = members.get(memberName);
|
||||||
return member == null ? JsonNull.INSTANCE : member;
|
return member == null ? JsonNull.INSTANCE : member;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to get the specified member as a JsonPrimitive element.
|
* Convenience method to get the specified member as a JsonPrimitive element.
|
||||||
*
|
*
|
||||||
* @param memberName name of the member being requested.
|
* @param memberName name of the member being requested.
|
||||||
* @return the JsonPrimitive corresponding to the specified member.
|
* @return the JsonPrimitive corresponding to the specified member.
|
||||||
*/
|
*/
|
||||||
public JsonPrimitive getAsJsonPrimitive(String memberName) {
|
public JsonPrimitive getAsJsonPrimitive(String memberName) {
|
||||||
return (JsonPrimitive) members.get(memberName);
|
return (JsonPrimitive) members.get(memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to get the specified member as a JsonArray.
|
* Convenience method to get the specified member as a JsonArray.
|
||||||
*
|
*
|
||||||
* @param memberName name of the member being requested.
|
* @param memberName name of the member being requested.
|
||||||
* @return the JsonArray corresponding to the specified member.
|
* @return the JsonArray corresponding to the specified member.
|
||||||
*/
|
*/
|
||||||
public JsonArray getAsJsonArray(String memberName) {
|
public JsonArray getAsJsonArray(String memberName) {
|
||||||
return (JsonArray) members.get(memberName);
|
return (JsonArray) members.get(memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to get the specified member as a JsonObject.
|
* Convenience method to get the specified member as a JsonObject.
|
||||||
*
|
*
|
||||||
* @param memberName name of the member being requested.
|
* @param memberName name of the member being requested.
|
||||||
* @return the JsonObject corresponding to the specified member.
|
* @return the JsonObject corresponding to the specified member.
|
||||||
*/
|
*/
|
||||||
public JsonObject getAsJsonObject(String memberName) {
|
public JsonObject getAsJsonObject(String memberName) {
|
||||||
return (JsonObject) members.get(memberName);
|
return (JsonObject) members.get(memberName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o == this) || (o instanceof JsonObject
|
return (o == this) || (o instanceof JsonObject
|
||||||
&& ((JsonObject) o).members.equals(members));
|
&& ((JsonObject) o).members.equals(members));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return members.hashCode();
|
return members.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception is raised if there is a serious issue that occurs during parsing of a Json
|
* This exception is raised if there is a serious issue that occurs during parsing of a Json
|
||||||
* string. One of the main usages for this class is for the Gson infrastructure. If the incoming
|
* string. One of the main usages for this class is for the Gson infrastructure. If the incoming
|
||||||
* Json is bad/malicious, an instance of this exception is raised.
|
* Json is bad/malicious, an instance of this exception is raised.
|
||||||
*
|
*
|
||||||
* <p>This exception is a {@link RuntimeException} because it is exposed to the client. Using a
|
* <p>This exception is a {@link RuntimeException} because it is exposed to the client. Using a
|
||||||
* {@link RuntimeException} avoids bad coding practices on the client side where they catch the
|
* {@link RuntimeException} avoids bad coding practices on the client side where they catch the
|
||||||
* exception and do nothing. It is often the case that you want to blow up if there is a parsing
|
* exception and do nothing. It is often the case that you want to blow up if there is a parsing
|
||||||
* error (i.e. often clients do not know how to recover from a {@link JsonParseException}.</p>
|
* error (i.e. often clients do not know how to recover from a {@link JsonParseException}.</p>
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public class JsonParseException extends RuntimeException {
|
public class JsonParseException extends RuntimeException {
|
||||||
static final long serialVersionUID = -4086729973971783390L;
|
static final long serialVersionUID = -4086729973971783390L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates exception with the specified message. If you are wrapping another exception, consider
|
* Creates exception with the specified message. If you are wrapping another exception, consider
|
||||||
* using {@link #JsonParseException(String, Throwable)} instead.
|
* using {@link #JsonParseException(String, Throwable)} instead.
|
||||||
*
|
*
|
||||||
* @param msg error message describing a possible cause of this exception.
|
* @param msg error message describing a possible cause of this exception.
|
||||||
*/
|
*/
|
||||||
public JsonParseException(String msg) {
|
public JsonParseException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates exception with the specified message and cause.
|
* Creates exception with the specified message and cause.
|
||||||
*
|
*
|
||||||
* @param msg error message describing what happened.
|
* @param msg error message describing what happened.
|
||||||
* @param cause root exception that caused this exception to be thrown.
|
* @param cause root exception that caused this exception to be thrown.
|
||||||
*/
|
*/
|
||||||
public JsonParseException(String msg, Throwable cause) {
|
public JsonParseException(String msg, Throwable cause) {
|
||||||
super(msg, cause);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates exception with the specified cause. Consider using
|
* Creates exception with the specified cause. Consider using
|
||||||
* {@link #JsonParseException(String, Throwable)} instead if you can describe what happened.
|
* {@link #JsonParseException(String, Throwable)} instead if you can describe what happened.
|
||||||
*
|
*
|
||||||
* @param cause root exception that caused this exception to be thrown.
|
* @param cause root exception that caused this exception to be thrown.
|
||||||
*/
|
*/
|
||||||
public JsonParseException(Throwable cause) {
|
public JsonParseException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,336 +1,336 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import com.google.gson.internal.LazilyParsedNumber;
|
import com.google.gson.internal.LazilyParsedNumber;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class representing a Json primitive value. A primitive value
|
* A class representing a Json primitive value. A primitive value
|
||||||
* is either a String, a Java primitive, or a Java primitive
|
* is either a String, a Java primitive, or a Java primitive
|
||||||
* wrapper type.
|
* wrapper type.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class JsonPrimitive extends JsonElement {
|
public final class JsonPrimitive extends JsonElement {
|
||||||
|
|
||||||
private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
|
private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
|
||||||
float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
|
float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
|
||||||
Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
|
Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
|
||||||
|
|
||||||
private Object value;
|
private Object value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a primitive containing a boolean value.
|
* Create a primitive containing a boolean value.
|
||||||
*
|
*
|
||||||
* @param bool the value to create the primitive with.
|
* @param bool the value to create the primitive with.
|
||||||
*/
|
*/
|
||||||
public JsonPrimitive(Boolean bool) {
|
public JsonPrimitive(Boolean bool) {
|
||||||
setValue(bool);
|
setValue(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a primitive containing a {@link Number}.
|
* Create a primitive containing a {@link Number}.
|
||||||
*
|
*
|
||||||
* @param number the value to create the primitive with.
|
* @param number the value to create the primitive with.
|
||||||
*/
|
*/
|
||||||
public JsonPrimitive(Number number) {
|
public JsonPrimitive(Number number) {
|
||||||
setValue(number);
|
setValue(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a primitive containing a String value.
|
* Create a primitive containing a String value.
|
||||||
*
|
*
|
||||||
* @param string the value to create the primitive with.
|
* @param string the value to create the primitive with.
|
||||||
*/
|
*/
|
||||||
public JsonPrimitive(String string) {
|
public JsonPrimitive(String string) {
|
||||||
setValue(string);
|
setValue(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a primitive containing a character. The character is turned into a one character String
|
* Create a primitive containing a character. The character is turned into a one character String
|
||||||
* since Json only supports String.
|
* since Json only supports String.
|
||||||
*
|
*
|
||||||
* @param c the value to create the primitive with.
|
* @param c the value to create the primitive with.
|
||||||
*/
|
*/
|
||||||
public JsonPrimitive(Character c) {
|
public JsonPrimitive(Character c) {
|
||||||
setValue(c);
|
setValue(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a primitive using the specified Object. It must be an instance of {@link Number}, a
|
* Create a primitive using the specified Object. It must be an instance of {@link Number}, a
|
||||||
* Java primitive type, or a String.
|
* Java primitive type, or a String.
|
||||||
*
|
*
|
||||||
* @param primitive the value to create the primitive with.
|
* @param primitive the value to create the primitive with.
|
||||||
*/
|
*/
|
||||||
JsonPrimitive(Object primitive) {
|
JsonPrimitive(Object primitive) {
|
||||||
setValue(primitive);
|
setValue(primitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValue(Object primitive) {
|
void setValue(Object primitive) {
|
||||||
if (primitive instanceof Character) {
|
if (primitive instanceof Character) {
|
||||||
// convert characters to strings since in JSON, characters are represented as a single
|
// convert characters to strings since in JSON, characters are represented as a single
|
||||||
// character string
|
// character string
|
||||||
char c = ((Character) primitive).charValue();
|
char c = ((Character) primitive).charValue();
|
||||||
this.value = String.valueOf(c);
|
this.value = String.valueOf(c);
|
||||||
} else {
|
} else {
|
||||||
$Gson$Preconditions.checkArgument(primitive instanceof Number
|
$Gson$Preconditions.checkArgument(primitive instanceof Number
|
||||||
|| isPrimitiveOrString(primitive));
|
|| isPrimitiveOrString(primitive));
|
||||||
this.value = primitive;
|
this.value = primitive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether this primitive contains a boolean value.
|
* Check whether this primitive contains a boolean value.
|
||||||
*
|
*
|
||||||
* @return true if this primitive contains a boolean value, false otherwise.
|
* @return true if this primitive contains a boolean value, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isBoolean() {
|
public boolean isBoolean() {
|
||||||
return value instanceof Boolean;
|
return value instanceof Boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link Boolean}.
|
* convenience method to get this element as a {@link Boolean}.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link Boolean}.
|
* @return get this element as a {@link Boolean}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
Boolean getAsBooleanWrapper() {
|
Boolean getAsBooleanWrapper() {
|
||||||
return (Boolean) value;
|
return (Boolean) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a boolean value.
|
* convenience method to get this element as a boolean value.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive boolean value.
|
* @return get this element as a primitive boolean value.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean getAsBoolean() {
|
public boolean getAsBoolean() {
|
||||||
if (isBoolean()) {
|
if (isBoolean()) {
|
||||||
return getAsBooleanWrapper().booleanValue();
|
return getAsBooleanWrapper().booleanValue();
|
||||||
} else {
|
} else {
|
||||||
// Check to see if the value as a String is "true" in any case.
|
// Check to see if the value as a String is "true" in any case.
|
||||||
return Boolean.parseBoolean(getAsString());
|
return Boolean.parseBoolean(getAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether this primitive contains a Number.
|
* Check whether this primitive contains a Number.
|
||||||
*
|
*
|
||||||
* @return true if this primitive contains a Number, false otherwise.
|
* @return true if this primitive contains a Number, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isNumber() {
|
public boolean isNumber() {
|
||||||
return value instanceof Number;
|
return value instanceof Number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a Number.
|
* convenience method to get this element as a Number.
|
||||||
*
|
*
|
||||||
* @return get this element as a Number.
|
* @return get this element as a Number.
|
||||||
* @throws NumberFormatException if the value contained is not a valid Number.
|
* @throws NumberFormatException if the value contained is not a valid Number.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Number getAsNumber() {
|
public Number getAsNumber() {
|
||||||
return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
|
return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether this primitive contains a String value.
|
* Check whether this primitive contains a String value.
|
||||||
*
|
*
|
||||||
* @return true if this primitive contains a String value, false otherwise.
|
* @return true if this primitive contains a String value, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isString() {
|
public boolean isString() {
|
||||||
return value instanceof String;
|
return value instanceof String;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a String.
|
* convenience method to get this element as a String.
|
||||||
*
|
*
|
||||||
* @return get this element as a String.
|
* @return get this element as a String.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getAsString() {
|
public String getAsString() {
|
||||||
if (isNumber()) {
|
if (isNumber()) {
|
||||||
return getAsNumber().toString();
|
return getAsNumber().toString();
|
||||||
} else if (isBoolean()) {
|
} else if (isBoolean()) {
|
||||||
return getAsBooleanWrapper().toString();
|
return getAsBooleanWrapper().toString();
|
||||||
} else {
|
} else {
|
||||||
return (String) value;
|
return (String) value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive double.
|
* convenience method to get this element as a primitive double.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive double.
|
* @return get this element as a primitive double.
|
||||||
* @throws NumberFormatException if the value contained is not a valid double.
|
* @throws NumberFormatException if the value contained is not a valid double.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double getAsDouble() {
|
public double getAsDouble() {
|
||||||
return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
|
return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link BigDecimal}.
|
* convenience method to get this element as a {@link BigDecimal}.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link BigDecimal}.
|
* @return get this element as a {@link BigDecimal}.
|
||||||
* @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}.
|
* @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getAsBigDecimal() {
|
public BigDecimal getAsBigDecimal() {
|
||||||
return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
|
return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a {@link BigInteger}.
|
* convenience method to get this element as a {@link BigInteger}.
|
||||||
*
|
*
|
||||||
* @return get this element as a {@link BigInteger}.
|
* @return get this element as a {@link BigInteger}.
|
||||||
* @throws NumberFormatException if the value contained is not a valid {@link BigInteger}.
|
* @throws NumberFormatException if the value contained is not a valid {@link BigInteger}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BigInteger getAsBigInteger() {
|
public BigInteger getAsBigInteger() {
|
||||||
return value instanceof BigInteger ?
|
return value instanceof BigInteger ?
|
||||||
(BigInteger) value : new BigInteger(value.toString());
|
(BigInteger) value : new BigInteger(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a float.
|
* convenience method to get this element as a float.
|
||||||
*
|
*
|
||||||
* @return get this element as a float.
|
* @return get this element as a float.
|
||||||
* @throws NumberFormatException if the value contained is not a valid float.
|
* @throws NumberFormatException if the value contained is not a valid float.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public float getAsFloat() {
|
public float getAsFloat() {
|
||||||
return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
|
return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive long.
|
* convenience method to get this element as a primitive long.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive long.
|
* @return get this element as a primitive long.
|
||||||
* @throws NumberFormatException if the value contained is not a valid long.
|
* @throws NumberFormatException if the value contained is not a valid long.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long getAsLong() {
|
public long getAsLong() {
|
||||||
return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
|
return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive short.
|
* convenience method to get this element as a primitive short.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive short.
|
* @return get this element as a primitive short.
|
||||||
* @throws NumberFormatException if the value contained is not a valid short value.
|
* @throws NumberFormatException if the value contained is not a valid short value.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public short getAsShort() {
|
public short getAsShort() {
|
||||||
return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
|
return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convenience method to get this element as a primitive integer.
|
* convenience method to get this element as a primitive integer.
|
||||||
*
|
*
|
||||||
* @return get this element as a primitive integer.
|
* @return get this element as a primitive integer.
|
||||||
* @throws NumberFormatException if the value contained is not a valid integer.
|
* @throws NumberFormatException if the value contained is not a valid integer.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getAsInt() {
|
public int getAsInt() {
|
||||||
return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
|
return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getAsByte() {
|
public byte getAsByte() {
|
||||||
return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
|
return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getAsCharacter() {
|
public char getAsCharacter() {
|
||||||
return getAsString().charAt(0);
|
return getAsString().charAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPrimitiveOrString(Object target) {
|
private static boolean isPrimitiveOrString(Object target) {
|
||||||
if (target instanceof String) {
|
if (target instanceof String) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> classOfPrimitive = target.getClass();
|
Class<?> classOfPrimitive = target.getClass();
|
||||||
for (Class<?> standardPrimitive : PRIMITIVE_TYPES) {
|
for (Class<?> standardPrimitive : PRIMITIVE_TYPES) {
|
||||||
if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
|
if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return 31;
|
return 31;
|
||||||
}
|
}
|
||||||
// Using recommended hashing algorithm from Effective Java for longs and doubles
|
// Using recommended hashing algorithm from Effective Java for longs and doubles
|
||||||
if (isIntegral(this)) {
|
if (isIntegral(this)) {
|
||||||
long value = getAsNumber().longValue();
|
long value = getAsNumber().longValue();
|
||||||
return (int) (value ^ (value >>> 32));
|
return (int) (value ^ (value >>> 32));
|
||||||
}
|
}
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
long value = Double.doubleToLongBits(getAsNumber().doubleValue());
|
long value = Double.doubleToLongBits(getAsNumber().doubleValue());
|
||||||
return (int) (value ^ (value >>> 32));
|
return (int) (value ^ (value >>> 32));
|
||||||
}
|
}
|
||||||
return value.hashCode();
|
return value.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JsonPrimitive other = (JsonPrimitive)obj;
|
JsonPrimitive other = (JsonPrimitive)obj;
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return other.value == null;
|
return other.value == null;
|
||||||
}
|
}
|
||||||
if (isIntegral(this) && isIntegral(other)) {
|
if (isIntegral(this) && isIntegral(other)) {
|
||||||
return getAsNumber().longValue() == other.getAsNumber().longValue();
|
return getAsNumber().longValue() == other.getAsNumber().longValue();
|
||||||
}
|
}
|
||||||
if (value instanceof Number && other.value instanceof Number) {
|
if (value instanceof Number && other.value instanceof Number) {
|
||||||
double a = getAsNumber().doubleValue();
|
double a = getAsNumber().doubleValue();
|
||||||
// Java standard types other than double return true for two NaN. So, need
|
// Java standard types other than double return true for two NaN. So, need
|
||||||
// special handling for double.
|
// special handling for double.
|
||||||
double b = other.getAsNumber().doubleValue();
|
double b = other.getAsNumber().doubleValue();
|
||||||
return a == b || (Double.isNaN(a) && Double.isNaN(b));
|
return a == b || (Double.isNaN(a) && Double.isNaN(b));
|
||||||
}
|
}
|
||||||
return value.equals(other.value);
|
return value.equals(other.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the specified number is an integral type
|
* Returns true if the specified number is an integral type
|
||||||
* (Long, Integer, Short, Byte, BigInteger)
|
* (Long, Integer, Short, Byte, BigInteger)
|
||||||
*/
|
*/
|
||||||
private static boolean isIntegral(JsonPrimitive primitive) {
|
private static boolean isIntegral(JsonPrimitive primitive) {
|
||||||
if (primitive.value instanceof Number) {
|
if (primitive.value instanceof Number) {
|
||||||
Number number = (Number) primitive.value;
|
Number number = (Number) primitive.value;
|
||||||
return number instanceof BigInteger || number instanceof Long || number instanceof Integer
|
return number instanceof BigInteger || number instanceof Long || number instanceof Integer
|
||||||
|| number instanceof Short || number instanceof Byte;
|
|| number instanceof Short || number instanceof Byte;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for serialization that is passed to a custom serializer during invocation of its
|
* Context for serialization that is passed to a custom serializer during invocation of its
|
||||||
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method.
|
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public interface JsonSerializationContext {
|
public interface JsonSerializationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes default serialization on the specified object.
|
* Invokes default serialization on the specified object.
|
||||||
*
|
*
|
||||||
* @param src the object that needs to be serialized.
|
* @param src the object that needs to be serialized.
|
||||||
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
|
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
|
||||||
*/
|
*/
|
||||||
public JsonElement serialize(Object src);
|
public JsonElement serialize(Object src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes default serialization on the specified object passing the specific type information.
|
* Invokes default serialization on the specified object passing the specific type information.
|
||||||
* It should never be invoked on the element received as a parameter of the
|
* It should never be invoked on the element received as a parameter of the
|
||||||
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. Doing
|
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. Doing
|
||||||
* so will result in an infinite loop since Gson will in-turn call the custom serializer again.
|
* so will result in an infinite loop since Gson will in-turn call the custom serializer again.
|
||||||
*
|
*
|
||||||
* @param src the object that needs to be serialized.
|
* @param src the object that needs to be serialized.
|
||||||
* @param typeOfSrc the actual genericized type of src object.
|
* @param typeOfSrc the actual genericized type of src object.
|
||||||
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
|
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
|
||||||
*/
|
*/
|
||||||
public JsonElement serialize(Object src, Type typeOfSrc);
|
public JsonElement serialize(Object src, Type typeOfSrc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,89 +1,89 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface representing a custom serializer for Json. You should write a custom serializer, if
|
* Interface representing a custom serializer for Json. You should write a custom serializer, if
|
||||||
* you are not happy with the default serialization done by Gson. You will also need to register
|
* you are not happy with the default serialization done by Gson. You will also need to register
|
||||||
* this serializer through {@link com.google.gson.GsonBuilder#registerTypeAdapter(Type, Object)}.
|
* this serializer through {@link com.google.gson.GsonBuilder#registerTypeAdapter(Type, Object)}.
|
||||||
*
|
*
|
||||||
* <p>Let us look at example where defining a serializer will be useful. The {@code Id} class
|
* <p>Let us look at example where defining a serializer will be useful. The {@code Id} class
|
||||||
* defined below has two fields: {@code clazz} and {@code value}.</p>
|
* defined below has two fields: {@code clazz} and {@code value}.</p>
|
||||||
*
|
*
|
||||||
* <p><pre>
|
* <p><pre>
|
||||||
* public class Id<T> {
|
* public class Id<T> {
|
||||||
* private final Class<T> clazz;
|
* private final Class<T> clazz;
|
||||||
* private final long value;
|
* private final long value;
|
||||||
*
|
*
|
||||||
* public Id(Class<T> clazz, long value) {
|
* public Id(Class<T> clazz, long value) {
|
||||||
* this.clazz = clazz;
|
* this.clazz = clazz;
|
||||||
* this.value = value;
|
* this.value = value;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public long getValue() {
|
* public long getValue() {
|
||||||
* return value;
|
* return value;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre></p>
|
* </pre></p>
|
||||||
*
|
*
|
||||||
* <p>The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be
|
* <p>The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be
|
||||||
* <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you just want the output to be
|
* <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you just want the output to be
|
||||||
* the value instead, which is {@code 20} in this case. You can achieve that by writing a custom
|
* the value instead, which is {@code 20} in this case. You can achieve that by writing a custom
|
||||||
* serializer:</p>
|
* serializer:</p>
|
||||||
*
|
*
|
||||||
* <p><pre>
|
* <p><pre>
|
||||||
* class IdSerializer implements JsonSerializer<Id>() {
|
* class IdSerializer implements JsonSerializer<Id>() {
|
||||||
* public JsonElement serialize(Id id, Type typeOfId, JsonSerializationContext context) {
|
* public JsonElement serialize(Id id, Type typeOfId, JsonSerializationContext context) {
|
||||||
* return new JsonPrimitive(id.getValue());
|
* return new JsonPrimitive(id.getValue());
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre></p>
|
* </pre></p>
|
||||||
*
|
*
|
||||||
* <p>You will also need to register {@code IdSerializer} with Gson as follows:</p>
|
* <p>You will also need to register {@code IdSerializer} with Gson as follows:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create();
|
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
|
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
|
||||||
* is more efficient than this interface's tree API.
|
* is more efficient than this interface's tree API.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*
|
*
|
||||||
* @param <T> type for which the serializer is being registered. It is possible that a serializer
|
* @param <T> type for which the serializer is being registered. It is possible that a serializer
|
||||||
* may be asked to serialize a specific generic type of the T.
|
* may be asked to serialize a specific generic type of the T.
|
||||||
*/
|
*/
|
||||||
public interface JsonSerializer<T> {
|
public interface JsonSerializer<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gson invokes this call-back method during serialization when it encounters a field of the
|
* Gson invokes this call-back method during serialization when it encounters a field of the
|
||||||
* specified type.
|
* specified type.
|
||||||
*
|
*
|
||||||
* <p>In the implementation of this call-back method, you should consider invoking
|
* <p>In the implementation of this call-back method, you should consider invoking
|
||||||
* {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
|
* {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
|
||||||
* non-trivial field of the {@code src} object. However, you should never invoke it on the
|
* non-trivial field of the {@code src} object. However, you should never invoke it on the
|
||||||
* {@code src} object itself since that will cause an infinite loop (Gson will call your
|
* {@code src} object itself since that will cause an infinite loop (Gson will call your
|
||||||
* call-back method again).</p>
|
* call-back method again).</p>
|
||||||
*
|
*
|
||||||
* @param src the object that needs to be converted to Json.
|
* @param src the object that needs to be converted to Json.
|
||||||
* @param typeOfSrc the actual type (fully genericized version) of the source object.
|
* @param typeOfSrc the actual type (fully genericized version) of the source object.
|
||||||
* @return a JsonElement corresponding to the specified object.
|
* @return a JsonElement corresponding to the specified object.
|
||||||
*/
|
*/
|
||||||
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
|
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,122 +1,122 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Google Inc.
|
* Copyright (C) 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import com.google.gson.internal.Streams;
|
import com.google.gson.internal.Streams;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.MalformedJsonException;
|
import com.google.gson.stream.MalformedJsonException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
|
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
|
||||||
* asynchronously.
|
* asynchronously.
|
||||||
*
|
*
|
||||||
* <p>This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
|
* <p>This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
|
||||||
* properly use this class across multiple threads, you will need to add some external
|
* properly use this class across multiple threads, you will need to add some external
|
||||||
* synchronization. For example:
|
* synchronization. For example:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
|
* JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
|
||||||
* JsonElement element;
|
* JsonElement element;
|
||||||
* synchronized (parser) { // synchronize on an object shared by threads
|
* synchronized (parser) { // synchronize on an object shared by threads
|
||||||
* if (parser.hasNext()) {
|
* if (parser.hasNext()) {
|
||||||
* element = parser.next();
|
* element = parser.next();
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public final class JsonStreamParser implements Iterator<JsonElement> {
|
public final class JsonStreamParser implements Iterator<JsonElement> {
|
||||||
private final JsonReader parser;
|
private final JsonReader parser;
|
||||||
private final Object lock;
|
private final Object lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param json The string containing JSON elements concatenated to each other.
|
* @param json The string containing JSON elements concatenated to each other.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public JsonStreamParser(String json) {
|
public JsonStreamParser(String json) {
|
||||||
this(new StringReader(json));
|
this(new StringReader(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param reader The data stream containing JSON elements concatenated to each other.
|
* @param reader The data stream containing JSON elements concatenated to each other.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public JsonStreamParser(Reader reader) {
|
public JsonStreamParser(Reader reader) {
|
||||||
parser = new JsonReader(reader);
|
parser = new JsonReader(reader);
|
||||||
parser.setLenient(true);
|
parser.setLenient(true);
|
||||||
lock = new Object();
|
lock = new Object();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the next available {@link JsonElement} on the reader. Null if none available.
|
* Returns the next available {@link JsonElement} on the reader. Null if none available.
|
||||||
*
|
*
|
||||||
* @return the next available {@link JsonElement} on the reader. Null if none available.
|
* @return the next available {@link JsonElement} on the reader. Null if none available.
|
||||||
* @throws JsonParseException if the incoming stream is malformed JSON.
|
* @throws JsonParseException if the incoming stream is malformed JSON.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public JsonElement next() throws JsonParseException {
|
public JsonElement next() throws JsonParseException {
|
||||||
if (!hasNext()) {
|
if (!hasNext()) {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Streams.parse(parser);
|
return Streams.parse(parser);
|
||||||
} catch (StackOverflowError e) {
|
} catch (StackOverflowError e) {
|
||||||
throw new JsonParseException("Failed parsing JSON source to Json", e);
|
throw new JsonParseException("Failed parsing JSON source to Json", e);
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
throw new JsonParseException("Failed parsing JSON source to Json", e);
|
throw new JsonParseException("Failed parsing JSON source to Json", e);
|
||||||
} catch (JsonParseException e) {
|
} catch (JsonParseException e) {
|
||||||
throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e;
|
throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a {@link JsonElement} is available on the input for consumption
|
* Returns true if a {@link JsonElement} is available on the input for consumption
|
||||||
* @return true if a {@link JsonElement} is available on the input, false otherwise
|
* @return true if a {@link JsonElement} is available on the input, false otherwise
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
return parser.peek() != JsonToken.END_DOCUMENT;
|
return parser.peek() != JsonToken.END_DOCUMENT;
|
||||||
} catch (MalformedJsonException e) {
|
} catch (MalformedJsonException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JsonIOException(e);
|
throw new JsonIOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This optional {@link Iterator} method is not relevant for stream parsing and hence is not
|
* This optional {@link Iterator} method is not relevant for stream parsing and hence is not
|
||||||
* implemented.
|
* implemented.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public void remove() {
|
public void remove() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,47 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Google Inc.
|
* Copyright (C) 2010 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception is raised when Gson attempts to read (or write) a malformed
|
* This exception is raised when Gson attempts to read (or write) a malformed
|
||||||
* JSON element.
|
* JSON element.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class JsonSyntaxException extends JsonParseException {
|
public final class JsonSyntaxException extends JsonParseException {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public JsonSyntaxException(String msg) {
|
public JsonSyntaxException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonSyntaxException(String msg, Throwable cause) {
|
public JsonSyntaxException(String msg, Throwable cause) {
|
||||||
super(msg, cause);
|
super(msg, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates exception with the specified cause. Consider using
|
* Creates exception with the specified cause. Consider using
|
||||||
* {@link #JsonSyntaxException(String, Throwable)} instead if you can
|
* {@link #JsonSyntaxException(String, Throwable)} instead if you can
|
||||||
* describe what actually happened.
|
* describe what actually happened.
|
||||||
*
|
*
|
||||||
* @param cause root exception that caused this exception to be thrown.
|
* @param cause root exception that caused this exception to be thrown.
|
||||||
*/
|
*/
|
||||||
public JsonSyntaxException(Throwable cause) {
|
public JsonSyntaxException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,58 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Google Inc.
|
* Copyright (C) 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the expected format for a {@code long} or {@code Long} type when its serialized.
|
* Defines the expected format for a {@code long} or {@code Long} type when its serialized.
|
||||||
*
|
*
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public enum LongSerializationPolicy {
|
public enum LongSerializationPolicy {
|
||||||
/**
|
/**
|
||||||
* This is the "default" serialization policy that will output a {@code long} object as a JSON
|
* This is the "default" serialization policy that will output a {@code long} object as a JSON
|
||||||
* number. For example, assume an object has a long field named "f" then the serialized output
|
* number. For example, assume an object has a long field named "f" then the serialized output
|
||||||
* would be:
|
* would be:
|
||||||
* {@code {"f":123}}.
|
* {@code {"f":123}}.
|
||||||
*/
|
*/
|
||||||
DEFAULT() {
|
DEFAULT() {
|
||||||
public JsonElement serialize(Long value) {
|
public JsonElement serialize(Long value) {
|
||||||
return new JsonPrimitive(value);
|
return new JsonPrimitive(value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes a long value as a quoted string. For example, assume an object has a long field
|
* Serializes a long value as a quoted string. For example, assume an object has a long field
|
||||||
* named "f" then the serialized output would be:
|
* named "f" then the serialized output would be:
|
||||||
* {@code {"f":"123"}}.
|
* {@code {"f":"123"}}.
|
||||||
*/
|
*/
|
||||||
STRING() {
|
STRING() {
|
||||||
public JsonElement serialize(Long value) {
|
public JsonElement serialize(Long value) {
|
||||||
return new JsonPrimitive(String.valueOf(value));
|
return new JsonPrimitive(String.valueOf(value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize this {@code value} using this serialization policy.
|
* Serialize this {@code value} using this serialization policy.
|
||||||
*
|
*
|
||||||
* @param value the long value to be serialized into a {@link JsonElement}
|
* @param value the long value to be serialized into a {@link JsonElement}
|
||||||
* @return the serialized version of {@code value}
|
* @return the serialized version of {@code value}
|
||||||
*/
|
*/
|
||||||
public abstract JsonElement serialize(Long value);
|
public abstract JsonElement serialize(Long value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,141 +1,141 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import com.google.gson.internal.GsonInternalAccess;
|
import com.google.gson.internal.GsonInternalAccess;
|
||||||
import com.google.gson.internal.Streams;
|
import com.google.gson.internal.Streams;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts a Gson 1.x tree-style adapter as a streaming TypeAdapter. Since the
|
* Adapts a Gson 1.x tree-style adapter as a streaming TypeAdapter. Since the
|
||||||
* tree adapter may be serialization-only or deserialization-only, this class
|
* tree adapter may be serialization-only or deserialization-only, this class
|
||||||
* has a facility to lookup a delegate type adapter on demand.
|
* has a facility to lookup a delegate type adapter on demand.
|
||||||
*/
|
*/
|
||||||
final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
final class TreeTypeAdapter<T> extends TypeAdapter<T> {
|
||||||
private final JsonSerializer<T> serializer;
|
private final JsonSerializer<T> serializer;
|
||||||
private final JsonDeserializer<T> deserializer;
|
private final JsonDeserializer<T> deserializer;
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
private final TypeToken<T> typeToken;
|
private final TypeToken<T> typeToken;
|
||||||
private final TypeAdapterFactory skipPast;
|
private final TypeAdapterFactory skipPast;
|
||||||
|
|
||||||
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
|
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
|
||||||
private TypeAdapter<T> delegate;
|
private TypeAdapter<T> delegate;
|
||||||
|
|
||||||
private TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
|
private TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
|
||||||
Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
|
Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
this.deserializer = deserializer;
|
this.deserializer = deserializer;
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
this.typeToken = typeToken;
|
this.typeToken = typeToken;
|
||||||
this.skipPast = skipPast;
|
this.skipPast = skipPast;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public T read(JsonReader in) throws IOException {
|
@Override public T read(JsonReader in) throws IOException {
|
||||||
if (deserializer == null) {
|
if (deserializer == null) {
|
||||||
return delegate().read(in);
|
return delegate().read(in);
|
||||||
}
|
}
|
||||||
JsonElement value = Streams.parse(in);
|
JsonElement value = Streams.parse(in);
|
||||||
if (value.isJsonNull()) {
|
if (value.isJsonNull()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext);
|
return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void write(JsonWriter out, T value) throws IOException {
|
@Override public void write(JsonWriter out, T value) throws IOException {
|
||||||
if (serializer == null) {
|
if (serializer == null) {
|
||||||
delegate().write(out, value);
|
delegate().write(out, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext);
|
JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext);
|
||||||
Streams.write(tree, out);
|
Streams.write(tree, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeAdapter<T> delegate() {
|
private TypeAdapter<T> delegate() {
|
||||||
TypeAdapter<T> d = delegate;
|
TypeAdapter<T> d = delegate;
|
||||||
return d != null
|
return d != null
|
||||||
? d
|
? d
|
||||||
: (delegate = GsonInternalAccess.INSTANCE.getNextAdapter(gson, skipPast, typeToken));
|
: (delegate = GsonInternalAccess.INSTANCE.getNextAdapter(gson, skipPast, typeToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new factory that will match each type against {@code exactType}.
|
* Returns a new factory that will match each type against {@code exactType}.
|
||||||
*/
|
*/
|
||||||
public static TypeAdapterFactory newFactory(TypeToken<?> exactType, Object typeAdapter) {
|
public static TypeAdapterFactory newFactory(TypeToken<?> exactType, Object typeAdapter) {
|
||||||
return new SingleTypeFactory(typeAdapter, exactType, false, null);
|
return new SingleTypeFactory(typeAdapter, exactType, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new factory that will match each type and its raw type against
|
* Returns a new factory that will match each type and its raw type against
|
||||||
* {@code exactType}.
|
* {@code exactType}.
|
||||||
*/
|
*/
|
||||||
public static TypeAdapterFactory newFactoryWithMatchRawType(
|
public static TypeAdapterFactory newFactoryWithMatchRawType(
|
||||||
TypeToken<?> exactType, Object typeAdapter) {
|
TypeToken<?> exactType, Object typeAdapter) {
|
||||||
// only bother matching raw types if exact type is a raw type
|
// only bother matching raw types if exact type is a raw type
|
||||||
boolean matchRawType = exactType.getType() == exactType.getRawType();
|
boolean matchRawType = exactType.getType() == exactType.getRawType();
|
||||||
return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null);
|
return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new factory that will match each type's raw type for assignability
|
* Returns a new factory that will match each type's raw type for assignability
|
||||||
* to {@code hierarchyType}.
|
* to {@code hierarchyType}.
|
||||||
*/
|
*/
|
||||||
public static TypeAdapterFactory newTypeHierarchyFactory(
|
public static TypeAdapterFactory newTypeHierarchyFactory(
|
||||||
Class<?> hierarchyType, Object typeAdapter) {
|
Class<?> hierarchyType, Object typeAdapter) {
|
||||||
return new SingleTypeFactory(typeAdapter, null, false, hierarchyType);
|
return new SingleTypeFactory(typeAdapter, null, false, hierarchyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SingleTypeFactory implements TypeAdapterFactory {
|
private static class SingleTypeFactory implements TypeAdapterFactory {
|
||||||
private final TypeToken<?> exactType;
|
private final TypeToken<?> exactType;
|
||||||
private final boolean matchRawType;
|
private final boolean matchRawType;
|
||||||
private final Class<?> hierarchyType;
|
private final Class<?> hierarchyType;
|
||||||
private final JsonSerializer<?> serializer;
|
private final JsonSerializer<?> serializer;
|
||||||
private final JsonDeserializer<?> deserializer;
|
private final JsonDeserializer<?> deserializer;
|
||||||
|
|
||||||
private SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType,
|
private SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType,
|
||||||
Class<?> hierarchyType) {
|
Class<?> hierarchyType) {
|
||||||
serializer = typeAdapter instanceof JsonSerializer
|
serializer = typeAdapter instanceof JsonSerializer
|
||||||
? (JsonSerializer<?>) typeAdapter
|
? (JsonSerializer<?>) typeAdapter
|
||||||
: null;
|
: null;
|
||||||
deserializer = typeAdapter instanceof JsonDeserializer
|
deserializer = typeAdapter instanceof JsonDeserializer
|
||||||
? (JsonDeserializer<?>) typeAdapter
|
? (JsonDeserializer<?>) typeAdapter
|
||||||
: null;
|
: null;
|
||||||
$Gson$Preconditions.checkArgument(serializer != null || deserializer != null);
|
$Gson$Preconditions.checkArgument(serializer != null || deserializer != null);
|
||||||
this.exactType = exactType;
|
this.exactType = exactType;
|
||||||
this.matchRawType = matchRawType;
|
this.matchRawType = matchRawType;
|
||||||
this.hierarchyType = hierarchyType;
|
this.hierarchyType = hierarchyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") // guarded by typeToken.equals() call
|
@SuppressWarnings("unchecked") // guarded by typeToken.equals() call
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||||
boolean matches = exactType != null
|
boolean matches = exactType != null
|
||||||
? exactType.equals(type) || matchRawType && exactType.getType() == type.getRawType()
|
? exactType.equals(type) || matchRawType && exactType.getType() == type.getRawType()
|
||||||
: hierarchyType.isAssignableFrom(type.getRawType());
|
: hierarchyType.isAssignableFrom(type.getRawType());
|
||||||
return matches
|
return matches
|
||||||
? new TreeTypeAdapter<T>((JsonSerializer<T>) serializer,
|
? new TreeTypeAdapter<T>((JsonSerializer<T>) serializer,
|
||||||
(JsonDeserializer<T>) deserializer, gson, type, this)
|
(JsonDeserializer<T>) deserializer, gson, type, this)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,283 +1,283 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.internal.bind.JsonTreeWriter;
|
import com.google.gson.internal.bind.JsonTreeWriter;
|
||||||
import com.google.gson.internal.bind.JsonTreeReader;
|
import com.google.gson.internal.bind.JsonTreeReader;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts Java objects to and from JSON.
|
* Converts Java objects to and from JSON.
|
||||||
*
|
*
|
||||||
* <h3>Defining a type's JSON form</h3>
|
* <h3>Defining a type's JSON form</h3>
|
||||||
* By default Gson converts application classes to JSON using its built-in type
|
* By default Gson converts application classes to JSON using its built-in type
|
||||||
* adapters. If Gson's default JSON conversion isn't appropriate for a type,
|
* adapters. If Gson's default JSON conversion isn't appropriate for a type,
|
||||||
* extend this class to customize the conversion. Here's an example of a type
|
* extend this class to customize the conversion. Here's an example of a type
|
||||||
* adapter for an (X,Y) coordinate point: <pre> {@code
|
* adapter for an (X,Y) coordinate point: <pre> {@code
|
||||||
*
|
*
|
||||||
* public class PointAdapter extends TypeAdapter<Point> {
|
* public class PointAdapter extends TypeAdapter<Point> {
|
||||||
* public Point read(JsonReader reader) throws IOException {
|
* public Point read(JsonReader reader) throws IOException {
|
||||||
* if (reader.peek() == JsonToken.NULL) {
|
* if (reader.peek() == JsonToken.NULL) {
|
||||||
* reader.nextNull();
|
* reader.nextNull();
|
||||||
* return null;
|
* return null;
|
||||||
* }
|
* }
|
||||||
* String xy = reader.nextString();
|
* String xy = reader.nextString();
|
||||||
* String[] parts = xy.split(",");
|
* String[] parts = xy.split(",");
|
||||||
* int x = Integer.parseInt(parts[0]);
|
* int x = Integer.parseInt(parts[0]);
|
||||||
* int y = Integer.parseInt(parts[1]);
|
* int y = Integer.parseInt(parts[1]);
|
||||||
* return new Point(x, y);
|
* return new Point(x, y);
|
||||||
* }
|
* }
|
||||||
* public void write(JsonWriter writer, Point value) throws IOException {
|
* public void write(JsonWriter writer, Point value) throws IOException {
|
||||||
* if (value == null) {
|
* if (value == null) {
|
||||||
* writer.nullValue();
|
* writer.nullValue();
|
||||||
* return;
|
* return;
|
||||||
* }
|
* }
|
||||||
* String xy = value.getX() + "," + value.getY();
|
* String xy = value.getX() + "," + value.getY();
|
||||||
* writer.value(xy);
|
* writer.value(xy);
|
||||||
* }
|
* }
|
||||||
* }}</pre>
|
* }}</pre>
|
||||||
* With this type adapter installed, Gson will convert {@code Points} to JSON as
|
* With this type adapter installed, Gson will convert {@code Points} to JSON as
|
||||||
* strings like {@code "5,8"} rather than objects like {@code {"x":5,"y":8}}. In
|
* strings like {@code "5,8"} rather than objects like {@code {"x":5,"y":8}}. In
|
||||||
* this case the type adapter binds a rich Java class to a compact JSON value.
|
* this case the type adapter binds a rich Java class to a compact JSON value.
|
||||||
*
|
*
|
||||||
* <p>The {@link #read(JsonReader) read()} method must read exactly one value
|
* <p>The {@link #read(JsonReader) read()} method must read exactly one value
|
||||||
* and {@link #write(JsonWriter,Object) write()} must write exactly one value.
|
* and {@link #write(JsonWriter,Object) write()} must write exactly one value.
|
||||||
* For primitive types this is means readers should make exactly one call to
|
* For primitive types this is means readers should make exactly one call to
|
||||||
* {@code nextBoolean()}, {@code nextDouble()}, {@code nextInt()}, {@code
|
* {@code nextBoolean()}, {@code nextDouble()}, {@code nextInt()}, {@code
|
||||||
* nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make
|
* nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make
|
||||||
* exactly one call to one of <code>value()</code> or <code>nullValue()</code>.
|
* exactly one call to one of <code>value()</code> or <code>nullValue()</code>.
|
||||||
* For arrays, type adapters should start with a call to {@code beginArray()},
|
* For arrays, type adapters should start with a call to {@code beginArray()},
|
||||||
* convert all elements, and finish with a call to {@code endArray()}. For
|
* convert all elements, and finish with a call to {@code endArray()}. For
|
||||||
* objects, they should start with {@code beginObject()}, convert the object,
|
* objects, they should start with {@code beginObject()}, convert the object,
|
||||||
* and finish with {@code endObject()}. Failing to convert a value or converting
|
* and finish with {@code endObject()}. Failing to convert a value or converting
|
||||||
* too many values may cause the application to crash.
|
* too many values may cause the application to crash.
|
||||||
*
|
*
|
||||||
* <p>Type adapters should be prepared to read null from the stream and write it
|
* <p>Type adapters should be prepared to read null from the stream and write it
|
||||||
* to the stream. Alternatively, they should use {@link #nullSafe()} method while
|
* to the stream. Alternatively, they should use {@link #nullSafe()} method while
|
||||||
* registering the type adapter with Gson. If your {@code Gson} instance
|
* registering the type adapter with Gson. If your {@code Gson} instance
|
||||||
* has been configured to {@link GsonBuilder#serializeNulls()}, these nulls will be
|
* has been configured to {@link GsonBuilder#serializeNulls()}, these nulls will be
|
||||||
* written to the final document. Otherwise the value (and the corresponding name
|
* written to the final document. Otherwise the value (and the corresponding name
|
||||||
* when writing to a JSON object) will be omitted automatically. In either case
|
* when writing to a JSON object) will be omitted automatically. In either case
|
||||||
* your type adapter must handle null.
|
* your type adapter must handle null.
|
||||||
*
|
*
|
||||||
* <p>To use a custom type adapter with Gson, you must <i>register</i> it with a
|
* <p>To use a custom type adapter with Gson, you must <i>register</i> it with a
|
||||||
* {@link GsonBuilder}: <pre> {@code
|
* {@link GsonBuilder}: <pre> {@code
|
||||||
*
|
*
|
||||||
* GsonBuilder builder = new GsonBuilder();
|
* GsonBuilder builder = new GsonBuilder();
|
||||||
* builder.registerTypeAdapter(Point.class, new PointAdapter());
|
* builder.registerTypeAdapter(Point.class, new PointAdapter());
|
||||||
* // if PointAdapter didn't check for nulls in its read/write methods, you should instead use
|
* // if PointAdapter didn't check for nulls in its read/write methods, you should instead use
|
||||||
* // builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe());
|
* // builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe());
|
||||||
* ...
|
* ...
|
||||||
* Gson gson = builder.create();
|
* Gson gson = builder.create();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
// non-Javadoc:
|
// non-Javadoc:
|
||||||
//
|
//
|
||||||
// <h3>JSON Conversion</h3>
|
// <h3>JSON Conversion</h3>
|
||||||
// <p>A type adapter registered with Gson is automatically invoked while serializing
|
// <p>A type adapter registered with Gson is automatically invoked while serializing
|
||||||
// or deserializing JSON. However, you can also use type adapters directly to serialize
|
// or deserializing JSON. However, you can also use type adapters directly to serialize
|
||||||
// and deserialize JSON. Here is an example for deserialization: <pre> {@code
|
// and deserialize JSON. Here is an example for deserialization: <pre> {@code
|
||||||
//
|
//
|
||||||
// String json = "{'origin':'0,0','points':['1,2','3,4']}";
|
// String json = "{'origin':'0,0','points':['1,2','3,4']}";
|
||||||
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
|
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
|
||||||
// Graph graph = graphAdapter.fromJson(json);
|
// Graph graph = graphAdapter.fromJson(json);
|
||||||
// }</pre>
|
// }</pre>
|
||||||
// And an example for serialization: <pre> {@code
|
// And an example for serialization: <pre> {@code
|
||||||
//
|
//
|
||||||
// Graph graph = new Graph(...);
|
// Graph graph = new Graph(...);
|
||||||
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
|
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
|
||||||
// String json = graphAdapter.toJson(graph);
|
// String json = graphAdapter.toJson(graph);
|
||||||
// }</pre>
|
// }</pre>
|
||||||
//
|
//
|
||||||
// <p>Type adapters are <strong>type-specific</strong>. For example, a {@code
|
// <p>Type adapters are <strong>type-specific</strong>. For example, a {@code
|
||||||
// TypeAdapter<Date>} can convert {@code Date} instances to JSON and JSON to
|
// TypeAdapter<Date>} can convert {@code Date} instances to JSON and JSON to
|
||||||
// instances of {@code Date}, but cannot convert any other types.
|
// instances of {@code Date}, but cannot convert any other types.
|
||||||
//
|
//
|
||||||
public abstract class TypeAdapter<T> {
|
public abstract class TypeAdapter<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes one JSON value (an array, object, string, number, boolean or null)
|
* Writes one JSON value (an array, object, string, number, boolean or null)
|
||||||
* for {@code value}.
|
* for {@code value}.
|
||||||
*
|
*
|
||||||
* @param value the Java object to write. May be null.
|
* @param value the Java object to write. May be null.
|
||||||
*/
|
*/
|
||||||
public abstract void write(JsonWriter out, T value) throws IOException;
|
public abstract void write(JsonWriter out, T value) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts {@code value} to a JSON document and writes it to {@code out}.
|
* Converts {@code value} to a JSON document and writes it to {@code out}.
|
||||||
* Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson}
|
* Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson}
|
||||||
* method, this write is strict. Create a {@link
|
* method, this write is strict. Create a {@link
|
||||||
* JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
|
* JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
|
||||||
* {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient
|
* {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient
|
||||||
* writing.
|
* writing.
|
||||||
*
|
*
|
||||||
* @param value the Java object to convert. May be null.
|
* @param value the Java object to convert. May be null.
|
||||||
*/
|
*/
|
||||||
/*public*/ final void toJson(Writer out, T value) throws IOException {
|
/*public*/ final void toJson(Writer out, T value) throws IOException {
|
||||||
JsonWriter writer = new JsonWriter(out);
|
JsonWriter writer = new JsonWriter(out);
|
||||||
write(writer, value);
|
write(writer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This wrapper method is used to make a type adapter null tolerant. In general, a
|
* This wrapper method is used to make a type adapter null tolerant. In general, a
|
||||||
* type adapter is required to handle nulls in write and read methods. Here is how this
|
* type adapter is required to handle nulls in write and read methods. Here is how this
|
||||||
* is typically done:<br>
|
* is typically done:<br>
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
*
|
*
|
||||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
|
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
|
||||||
* new TypeAdapter<Foo>() {
|
* new TypeAdapter<Foo>() {
|
||||||
* public Foo read(JsonReader in) throws IOException {
|
* public Foo read(JsonReader in) throws IOException {
|
||||||
* if (in.peek() == JsonToken.NULL) {
|
* if (in.peek() == JsonToken.NULL) {
|
||||||
* in.nextNull();
|
* in.nextNull();
|
||||||
* return null;
|
* return null;
|
||||||
* }
|
* }
|
||||||
* // read a Foo from in and return it
|
* // read a Foo from in and return it
|
||||||
* }
|
* }
|
||||||
* public void write(JsonWriter out, Foo src) throws IOException {
|
* public void write(JsonWriter out, Foo src) throws IOException {
|
||||||
* if (src == null) {
|
* if (src == null) {
|
||||||
* out.nullValue();
|
* out.nullValue();
|
||||||
* return;
|
* return;
|
||||||
* }
|
* }
|
||||||
* // write src as JSON to out
|
* // write src as JSON to out
|
||||||
* }
|
* }
|
||||||
* }).create();
|
* }).create();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* You can avoid this boilerplate handling of nulls by wrapping your type adapter with
|
* You can avoid this boilerplate handling of nulls by wrapping your type adapter with
|
||||||
* this method. Here is how we will rewrite the above example:
|
* this method. Here is how we will rewrite the above example:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
*
|
*
|
||||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
|
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
|
||||||
* new TypeAdapter<Foo>() {
|
* new TypeAdapter<Foo>() {
|
||||||
* public Foo read(JsonReader in) throws IOException {
|
* public Foo read(JsonReader in) throws IOException {
|
||||||
* // read a Foo from in and return it
|
* // read a Foo from in and return it
|
||||||
* }
|
* }
|
||||||
* public void write(JsonWriter out, Foo src) throws IOException {
|
* public void write(JsonWriter out, Foo src) throws IOException {
|
||||||
* // write src as JSON to out
|
* // write src as JSON to out
|
||||||
* }
|
* }
|
||||||
* }.nullSafe()).create();
|
* }.nullSafe()).create();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* Note that we didn't need to check for nulls in our type adapter after we used nullSafe.
|
* Note that we didn't need to check for nulls in our type adapter after we used nullSafe.
|
||||||
*/
|
*/
|
||||||
public final TypeAdapter<T> nullSafe() {
|
public final TypeAdapter<T> nullSafe() {
|
||||||
return new TypeAdapter<T>() {
|
return new TypeAdapter<T>() {
|
||||||
@Override public void write(JsonWriter out, T value) throws IOException {
|
@Override public void write(JsonWriter out, T value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
} else {
|
} else {
|
||||||
TypeAdapter.this.write(out, value);
|
TypeAdapter.this.write(out, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override public T read(JsonReader reader) throws IOException {
|
@Override public T read(JsonReader reader) throws IOException {
|
||||||
if (reader.peek() == JsonToken.NULL) {
|
if (reader.peek() == JsonToken.NULL) {
|
||||||
reader.nextNull();
|
reader.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return TypeAdapter.this.read(reader);
|
return TypeAdapter.this.read(reader);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts {@code value} to a JSON document. Unlike Gson's similar {@link
|
* Converts {@code value} to a JSON document. Unlike Gson's similar {@link
|
||||||
* Gson#toJson(Object) toJson} method, this write is strict. Create a {@link
|
* Gson#toJson(Object) toJson} method, this write is strict. Create a {@link
|
||||||
* JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
|
* JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
|
||||||
* {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient
|
* {@link #write(com.google.gson.stream.JsonWriter, Object)} for lenient
|
||||||
* writing.
|
* writing.
|
||||||
*
|
*
|
||||||
* @param value the Java object to convert. May be null.
|
* @param value the Java object to convert. May be null.
|
||||||
*/
|
*/
|
||||||
/*public*/ final String toJson(T value) throws IOException {
|
/*public*/ final String toJson(T value) throws IOException {
|
||||||
StringWriter stringWriter = new StringWriter();
|
StringWriter stringWriter = new StringWriter();
|
||||||
toJson(stringWriter, value);
|
toJson(stringWriter, value);
|
||||||
return stringWriter.toString();
|
return stringWriter.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts {@code value} to a JSON tree.
|
* Converts {@code value} to a JSON tree.
|
||||||
*
|
*
|
||||||
* @param value the Java object to convert. May be null.
|
* @param value the Java object to convert. May be null.
|
||||||
* @return the converted JSON tree. May be {@link JsonNull}.
|
* @return the converted JSON tree. May be {@link JsonNull}.
|
||||||
*/
|
*/
|
||||||
/*public*/ final JsonElement toJsonTree(T value) {
|
/*public*/ final JsonElement toJsonTree(T value) {
|
||||||
try {
|
try {
|
||||||
JsonTreeWriter jsonWriter = new JsonTreeWriter();
|
JsonTreeWriter jsonWriter = new JsonTreeWriter();
|
||||||
jsonWriter.setLenient(true);
|
jsonWriter.setLenient(true);
|
||||||
write(jsonWriter, value);
|
write(jsonWriter, value);
|
||||||
return jsonWriter.get();
|
return jsonWriter.get();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JsonIOException(e);
|
throw new JsonIOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads one JSON value (an array, object, string, number, boolean or null)
|
* Reads one JSON value (an array, object, string, number, boolean or null)
|
||||||
* and converts it to a Java object. Returns the converted object.
|
* and converts it to a Java object. Returns the converted object.
|
||||||
*
|
*
|
||||||
* @return the converted Java object. May be null.
|
* @return the converted Java object. May be null.
|
||||||
*/
|
*/
|
||||||
public abstract T read(JsonReader in) throws IOException;
|
public abstract T read(JsonReader in) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the JSON document in {@code in} to a Java object. Unlike Gson's
|
* Converts the JSON document in {@code in} to a Java object. Unlike Gson's
|
||||||
* similar {@link Gson#fromJson(java.io.Reader, Class) fromJson} method, this
|
* similar {@link Gson#fromJson(java.io.Reader, Class) fromJson} method, this
|
||||||
* read is strict. Create a {@link JsonReader#setLenient(boolean) lenient}
|
* read is strict. Create a {@link JsonReader#setLenient(boolean) lenient}
|
||||||
* {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading.
|
* {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading.
|
||||||
*
|
*
|
||||||
* @return the converted Java object. May be null.
|
* @return the converted Java object. May be null.
|
||||||
*/
|
*/
|
||||||
/*public*/ final T fromJson(Reader in) throws IOException {
|
/*public*/ final T fromJson(Reader in) throws IOException {
|
||||||
JsonReader reader = new JsonReader(in);
|
JsonReader reader = new JsonReader(in);
|
||||||
reader.setLenient(true); // TODO: non-lenient?
|
reader.setLenient(true); // TODO: non-lenient?
|
||||||
return read(reader);
|
return read(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the JSON document in {@code json} to a Java object. Unlike Gson's
|
* Converts the JSON document in {@code json} to a Java object. Unlike Gson's
|
||||||
* similar {@link Gson#fromJson(String, Class) fromJson} method, this read is
|
* similar {@link Gson#fromJson(String, Class) fromJson} method, this read is
|
||||||
* strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code
|
* strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code
|
||||||
* JsonReader} and call {@link #read(JsonReader)} for lenient reading.
|
* JsonReader} and call {@link #read(JsonReader)} for lenient reading.
|
||||||
*
|
*
|
||||||
* @return the converted Java object. May be null.
|
* @return the converted Java object. May be null.
|
||||||
*/
|
*/
|
||||||
/*public*/ final T fromJson(String json) throws IOException {
|
/*public*/ final T fromJson(String json) throws IOException {
|
||||||
return fromJson(new StringReader(json));
|
return fromJson(new StringReader(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts {@code jsonTree} to a Java object.
|
* Converts {@code jsonTree} to a Java object.
|
||||||
*
|
*
|
||||||
* @param jsonTree the Java object to convert. May be {@link JsonNull}.
|
* @param jsonTree the Java object to convert. May be {@link JsonNull}.
|
||||||
*/
|
*/
|
||||||
/*public*/ final T fromJsonTree(JsonElement jsonTree) {
|
/*public*/ final T fromJsonTree(JsonElement jsonTree) {
|
||||||
try {
|
try {
|
||||||
JsonReader jsonReader = new JsonTreeReader(jsonTree);
|
JsonReader jsonReader = new JsonTreeReader(jsonTree);
|
||||||
jsonReader.setLenient(true);
|
jsonReader.setLenient(true);
|
||||||
return read(jsonReader);
|
return read(jsonReader);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JsonIOException(e);
|
throw new JsonIOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,170 +1,170 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates type adapters for set of related types. Type adapter factories are
|
* Creates type adapters for set of related types. Type adapter factories are
|
||||||
* most useful when several types share similar structure in their JSON form.
|
* most useful when several types share similar structure in their JSON form.
|
||||||
*
|
*
|
||||||
* <h3>Example: Converting enums to lowercase</h3>
|
* <h3>Example: Converting enums to lowercase</h3>
|
||||||
* In this example, we implement a factory that creates type adapters for all
|
* In this example, we implement a factory that creates type adapters for all
|
||||||
* enums. The type adapters will write enums in lowercase, despite the fact
|
* enums. The type adapters will write enums in lowercase, despite the fact
|
||||||
* that they're defined in {@code CONSTANT_CASE} in the corresponding Java
|
* that they're defined in {@code CONSTANT_CASE} in the corresponding Java
|
||||||
* model: <pre> {@code
|
* model: <pre> {@code
|
||||||
*
|
*
|
||||||
* public class LowercaseEnumTypeAdapterFactory implements TypeAdapter.Factory {
|
* public class LowercaseEnumTypeAdapterFactory implements TypeAdapter.Factory {
|
||||||
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||||
* Class<T> rawType = (Class<T>) type.getRawType();
|
* Class<T> rawType = (Class<T>) type.getRawType();
|
||||||
* if (!rawType.isEnum()) {
|
* if (!rawType.isEnum()) {
|
||||||
* return null;
|
* return null;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
|
* final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
|
||||||
* for (T constant : rawType.getEnumConstants()) {
|
* for (T constant : rawType.getEnumConstants()) {
|
||||||
* lowercaseToConstant.put(toLowercase(constant), constant);
|
* lowercaseToConstant.put(toLowercase(constant), constant);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* return new TypeAdapter<T>() {
|
* return new TypeAdapter<T>() {
|
||||||
* public void write(JsonWriter out, T value) throws IOException {
|
* public void write(JsonWriter out, T value) throws IOException {
|
||||||
* if (value == null) {
|
* if (value == null) {
|
||||||
* out.nullValue();
|
* out.nullValue();
|
||||||
* } else {
|
* } else {
|
||||||
* out.value(toLowercase(value));
|
* out.value(toLowercase(value));
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public T read(JsonReader reader) throws IOException {
|
* public T read(JsonReader reader) throws IOException {
|
||||||
* if (reader.peek() == JsonToken.NULL) {
|
* if (reader.peek() == JsonToken.NULL) {
|
||||||
* reader.nextNull();
|
* reader.nextNull();
|
||||||
* return null;
|
* return null;
|
||||||
* } else {
|
* } else {
|
||||||
* return lowercaseToConstant.get(reader.nextString());
|
* return lowercaseToConstant.get(reader.nextString());
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* };
|
* };
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* private String toLowercase(Object o) {
|
* private String toLowercase(Object o) {
|
||||||
* return o.toString().toLowerCase(Locale.US);
|
* return o.toString().toLowerCase(Locale.US);
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* <p>Type adapter factories select which types they provide type adapters
|
* <p>Type adapter factories select which types they provide type adapters
|
||||||
* for. If a factory cannot support a given type, it must return null when
|
* for. If a factory cannot support a given type, it must return null when
|
||||||
* that type is passed to {@link #create}. Factories should expect {@code
|
* that type is passed to {@link #create}. Factories should expect {@code
|
||||||
* create()} to be called on them for many types and should return null for
|
* create()} to be called on them for many types and should return null for
|
||||||
* most of those types. In the above example the factory returns null for
|
* most of those types. In the above example the factory returns null for
|
||||||
* calls to {@code create()} where {@code type} is not an enum.
|
* calls to {@code create()} where {@code type} is not an enum.
|
||||||
*
|
*
|
||||||
* <p>A factory is typically called once per type, but the returned type
|
* <p>A factory is typically called once per type, but the returned type
|
||||||
* adapter may be used many times. It is most efficient to do expensive work
|
* adapter may be used many times. It is most efficient to do expensive work
|
||||||
* like reflection in {@code create()} so that the type adapter's {@code
|
* like reflection in {@code create()} so that the type adapter's {@code
|
||||||
* read()} and {@code write()} methods can be very fast. In this example the
|
* read()} and {@code write()} methods can be very fast. In this example the
|
||||||
* mapping from lowercase name to enum value is computed eagerly.
|
* mapping from lowercase name to enum value is computed eagerly.
|
||||||
*
|
*
|
||||||
* <p>As with type adapters, factories must be <i>registered</i> with a {@link
|
* <p>As with type adapters, factories must be <i>registered</i> with a {@link
|
||||||
* com.google.gson.GsonBuilder} for them to take effect: <pre> {@code
|
* com.google.gson.GsonBuilder} for them to take effect: <pre> {@code
|
||||||
*
|
*
|
||||||
* GsonBuilder builder = new GsonBuilder();
|
* GsonBuilder builder = new GsonBuilder();
|
||||||
* builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
|
* builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
|
||||||
* ...
|
* ...
|
||||||
* Gson gson = builder.create();
|
* Gson gson = builder.create();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* If multiple factories support the same type, the factory registered earlier
|
* If multiple factories support the same type, the factory registered earlier
|
||||||
* takes precedence.
|
* takes precedence.
|
||||||
*
|
*
|
||||||
* <h3>Example: composing other type adapters</h3>
|
* <h3>Example: composing other type adapters</h3>
|
||||||
* In this example we implement a factory for Guava's {@code Multiset}
|
* In this example we implement a factory for Guava's {@code Multiset}
|
||||||
* collection type. The factory can be used to create type adapters for
|
* collection type. The factory can be used to create type adapters for
|
||||||
* multisets of any element type: the type adapter for {@code
|
* multisets of any element type: the type adapter for {@code
|
||||||
* Multiset<String>} is different from the type adapter for {@code
|
* Multiset<String>} is different from the type adapter for {@code
|
||||||
* Multiset<URL>}.
|
* Multiset<URL>}.
|
||||||
*
|
*
|
||||||
* <p>The type adapter <i>delegates</i> to another type adapter for the
|
* <p>The type adapter <i>delegates</i> to another type adapter for the
|
||||||
* multiset elements. It figures out the element type by reflecting on the
|
* multiset elements. It figures out the element type by reflecting on the
|
||||||
* multiset's type token. A {@code Gson} is passed in to {@code create} for
|
* multiset's type token. A {@code Gson} is passed in to {@code create} for
|
||||||
* just this purpose: <pre> {@code
|
* just this purpose: <pre> {@code
|
||||||
*
|
*
|
||||||
* public class MultisetTypeAdapterFactory implements TypeAdapter.Factory {
|
* public class MultisetTypeAdapterFactory implements TypeAdapter.Factory {
|
||||||
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
* Type type = typeToken.getType();
|
* Type type = typeToken.getType();
|
||||||
* if (typeToken.getRawType() != Multiset.class
|
* if (typeToken.getRawType() != Multiset.class
|
||||||
* || !(type instanceof ParameterizedType)) {
|
* || !(type instanceof ParameterizedType)) {
|
||||||
* return null;
|
* return null;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
* Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
* TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType));
|
* TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType));
|
||||||
* return (TypeAdapter<T>) newMultisetAdapter(elementAdapter);
|
* return (TypeAdapter<T>) newMultisetAdapter(elementAdapter);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* private <E> TypeAdapter<Multiset<E>> newMultisetAdapter(
|
* private <E> TypeAdapter<Multiset<E>> newMultisetAdapter(
|
||||||
* final TypeAdapter<E> elementAdapter) {
|
* final TypeAdapter<E> elementAdapter) {
|
||||||
* return new TypeAdapter<Multiset<E>>() {
|
* return new TypeAdapter<Multiset<E>>() {
|
||||||
* public void write(JsonWriter out, Multiset<E> value) throws IOException {
|
* public void write(JsonWriter out, Multiset<E> value) throws IOException {
|
||||||
* if (value == null) {
|
* if (value == null) {
|
||||||
* out.nullValue();
|
* out.nullValue();
|
||||||
* return;
|
* return;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* out.beginArray();
|
* out.beginArray();
|
||||||
* for (Multiset.Entry<E> entry : value.entrySet()) {
|
* for (Multiset.Entry<E> entry : value.entrySet()) {
|
||||||
* out.value(entry.getCount());
|
* out.value(entry.getCount());
|
||||||
* elementAdapter.write(out, entry.getElement());
|
* elementAdapter.write(out, entry.getElement());
|
||||||
* }
|
* }
|
||||||
* out.endArray();
|
* out.endArray();
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public Multiset<E> read(JsonReader in) throws IOException {
|
* public Multiset<E> read(JsonReader in) throws IOException {
|
||||||
* if (in.peek() == JsonToken.NULL) {
|
* if (in.peek() == JsonToken.NULL) {
|
||||||
* in.nextNull();
|
* in.nextNull();
|
||||||
* return null;
|
* return null;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Multiset<E> result = LinkedHashMultiset.create();
|
* Multiset<E> result = LinkedHashMultiset.create();
|
||||||
* in.beginArray();
|
* in.beginArray();
|
||||||
* while (in.hasNext()) {
|
* while (in.hasNext()) {
|
||||||
* int count = in.nextInt();
|
* int count = in.nextInt();
|
||||||
* E element = elementAdapter.read(in);
|
* E element = elementAdapter.read(in);
|
||||||
* result.add(element, count);
|
* result.add(element, count);
|
||||||
* }
|
* }
|
||||||
* in.endArray();
|
* in.endArray();
|
||||||
* return result;
|
* return result;
|
||||||
* }
|
* }
|
||||||
* };
|
* };
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* Delegating from one type adapter to another is extremely powerful; it's
|
* Delegating from one type adapter to another is extremely powerful; it's
|
||||||
* the foundation of how Gson converts Java objects and collections. Whenever
|
* the foundation of how Gson converts Java objects and collections. Whenever
|
||||||
* possible your factory should retrieve its delegate type adapter in the
|
* possible your factory should retrieve its delegate type adapter in the
|
||||||
* {@code create()} method; this ensures potentially-expensive type adapter
|
* {@code create()} method; this ensures potentially-expensive type adapter
|
||||||
* creation happens only once.
|
* creation happens only once.
|
||||||
*
|
*
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public interface TypeAdapterFactory {
|
public interface TypeAdapterFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a type adapter for {@code type}, or null if this factory doesn't
|
* Returns a type adapter for {@code type}, or null if this factory doesn't
|
||||||
* support {@code type}.
|
* support {@code type}.
|
||||||
*/
|
*/
|
||||||
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
|
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,79 +1,79 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.annotations;
|
package com.google.gson.annotations;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An annotation that indicates this member should be exposed for JSON
|
* An annotation that indicates this member should be exposed for JSON
|
||||||
* serialization or deserialization.
|
* serialization or deserialization.
|
||||||
*
|
*
|
||||||
* <p>This annotation has no effect unless you build {@link com.google.gson.Gson}
|
* <p>This annotation has no effect unless you build {@link com.google.gson.Gson}
|
||||||
* with a {@link com.google.gson.GsonBuilder} and invoke
|
* with a {@link com.google.gson.GsonBuilder} and invoke
|
||||||
* {@link com.google.gson.GsonBuilder#excludeFieldsWithoutExposeAnnotation()}
|
* {@link com.google.gson.GsonBuilder#excludeFieldsWithoutExposeAnnotation()}
|
||||||
* method.</p>
|
* method.</p>
|
||||||
*
|
*
|
||||||
* <p>Here is an example of how this annotation is meant to be used:
|
* <p>Here is an example of how this annotation is meant to be used:
|
||||||
* <p><pre>
|
* <p><pre>
|
||||||
* public class User {
|
* public class User {
|
||||||
* @Expose private String firstName;
|
* @Expose private String firstName;
|
||||||
* @Expose(serialize = false) private String lastName;
|
* @Expose(serialize = false) private String lastName;
|
||||||
* @Expose (serialize = false, deserialize = false) private String emailAddress;
|
* @Expose (serialize = false, deserialize = false) private String emailAddress;
|
||||||
* private String password;
|
* private String password;
|
||||||
* }
|
* }
|
||||||
* </pre></p>
|
* </pre></p>
|
||||||
* If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
|
* If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
|
||||||
* methods will use the {@code password} field along-with {@code firstName}, {@code lastName},
|
* methods will use the {@code password} field along-with {@code firstName}, {@code lastName},
|
||||||
* and {@code emailAddress} for serialization and deserialization. However, if you created Gson
|
* and {@code emailAddress} for serialization and deserialization. However, if you created Gson
|
||||||
* with {@code Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()}
|
* with {@code Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()}
|
||||||
* then the {@code toJson()} and {@code fromJson()} methods of Gson will exclude the
|
* then the {@code toJson()} and {@code fromJson()} methods of Gson will exclude the
|
||||||
* {@code password} field. This is because the {@code password} field is not marked with the
|
* {@code password} field. This is because the {@code password} field is not marked with the
|
||||||
* {@code @Expose} annotation. Gson will also exclude {@code lastName} and {@code emailAddress}
|
* {@code @Expose} annotation. Gson will also exclude {@code lastName} and {@code emailAddress}
|
||||||
* from serialization since {@code serialize} is set to {@code false}. Similarly, Gson will
|
* from serialization since {@code serialize} is set to {@code false}. Similarly, Gson will
|
||||||
* exclude {@code emailAddress} from deserialization since {@code deserialize} is set to false.
|
* exclude {@code emailAddress} from deserialization since {@code deserialize} is set to false.
|
||||||
*
|
*
|
||||||
* <p>Note that another way to achieve the same effect would have been to just mark the
|
* <p>Note that another way to achieve the same effect would have been to just mark the
|
||||||
* {@code password} field as {@code transient}, and Gson would have excluded it even with default
|
* {@code password} field as {@code transient}, and Gson would have excluded it even with default
|
||||||
* settings. The {@code @Expose} annotation is useful in a style of programming where you want to
|
* settings. The {@code @Expose} annotation is useful in a style of programming where you want to
|
||||||
* explicitly specify all fields that should get considered for serialization or deserialization.
|
* explicitly specify all fields that should get considered for serialization or deserialization.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface Expose {
|
public @interface Expose {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If {@code true}, the field marked with this annotation is written out in the JSON while
|
* If {@code true}, the field marked with this annotation is written out in the JSON while
|
||||||
* serializing. If {@code false}, the field marked with this annotation is skipped from the
|
* serializing. If {@code false}, the field marked with this annotation is skipped from the
|
||||||
* serialized output. Defaults to {@code true}.
|
* serialized output. Defaults to {@code true}.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public boolean serialize() default true;
|
public boolean serialize() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
|
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
|
||||||
* If {@code false}, the field marked with this annotation is skipped during deserialization.
|
* If {@code false}, the field marked with this annotation is skipped during deserialization.
|
||||||
* Defaults to {@code true}.
|
* Defaults to {@code true}.
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public boolean deserialize() default true;
|
public boolean deserialize() default true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +1,74 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.annotations;
|
package com.google.gson.annotations;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An annotation that indicates this member should be serialized to JSON with
|
* An annotation that indicates this member should be serialized to JSON with
|
||||||
* the provided name value as its field name.
|
* the provided name value as its field name.
|
||||||
*
|
*
|
||||||
* <p>This annotation will override any {@link com.google.gson.FieldNamingPolicy}, including
|
* <p>This annotation will override any {@link com.google.gson.FieldNamingPolicy}, including
|
||||||
* the default field naming policy, that may have been set on the {@link com.google.gson.Gson}
|
* the default field naming policy, that may have been set on the {@link com.google.gson.Gson}
|
||||||
* instance. A different naming policy can set using the {@code GsonBuilder} class. See
|
* instance. A different naming policy can set using the {@code GsonBuilder} class. See
|
||||||
* {@link com.google.gson.GsonBuilder#setFieldNamingPolicy(com.google.gson.FieldNamingPolicy)}
|
* {@link com.google.gson.GsonBuilder#setFieldNamingPolicy(com.google.gson.FieldNamingPolicy)}
|
||||||
* for more information.</p>
|
* for more information.</p>
|
||||||
*
|
*
|
||||||
* <p>Here is an example of how this annotation is meant to be used:</p>
|
* <p>Here is an example of how this annotation is meant to be used:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class SomeClassWithFields {
|
* public class SomeClassWithFields {
|
||||||
* @SerializedName("name") private final String someField;
|
* @SerializedName("name") private final String someField;
|
||||||
* private final String someOtherField;
|
* private final String someOtherField;
|
||||||
*
|
*
|
||||||
* public SomeClassWithFields(String a, String b) {
|
* public SomeClassWithFields(String a, String b) {
|
||||||
* this.someField = a;
|
* this.someField = a;
|
||||||
* this.someOtherField = b;
|
* this.someOtherField = b;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>The following shows the output that is generated when serializing an instance of the
|
* <p>The following shows the output that is generated when serializing an instance of the
|
||||||
* above example class:</p>
|
* above example class:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* SomeClassWithFields objectToSerialize = new SomeClassWithFields("a", "b");
|
* SomeClassWithFields objectToSerialize = new SomeClassWithFields("a", "b");
|
||||||
* Gson gson = new Gson();
|
* Gson gson = new Gson();
|
||||||
* String jsonRepresentation = gson.toJson(objectToSerialize);
|
* String jsonRepresentation = gson.toJson(objectToSerialize);
|
||||||
* System.out.println(jsonRepresentation);
|
* System.out.println(jsonRepresentation);
|
||||||
*
|
*
|
||||||
* ===== OUTPUT =====
|
* ===== OUTPUT =====
|
||||||
* {"name":"a","someOtherField":"b"}
|
* {"name":"a","someOtherField":"b"}
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>NOTE: The value you specify in this annotation must be a valid JSON field name.</p>
|
* <p>NOTE: The value you specify in this annotation must be a valid JSON field name.</p>
|
||||||
*
|
*
|
||||||
* @see com.google.gson.FieldNamingPolicy
|
* @see com.google.gson.FieldNamingPolicy
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface SerializedName {
|
public @interface SerializedName {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the desired name of the field when it is serialized
|
* @return the desired name of the field when it is serialized
|
||||||
*/
|
*/
|
||||||
String value();
|
String value();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.annotations;
|
package com.google.gson.annotations;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An annotation that indicates the version number since a member or a type has been present.
|
* An annotation that indicates the version number since a member or a type has been present.
|
||||||
* This annotation is useful to manage versioning of your Json classes for a web-service.
|
* This annotation is useful to manage versioning of your Json classes for a web-service.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This annotation has no effect unless you build {@link com.google.gson.Gson} with a
|
* This annotation has no effect unless you build {@link com.google.gson.Gson} with a
|
||||||
* {@link com.google.gson.GsonBuilder} and invoke
|
* {@link com.google.gson.GsonBuilder} and invoke
|
||||||
* {@link com.google.gson.GsonBuilder#setVersion(double)} method.
|
* {@link com.google.gson.GsonBuilder#setVersion(double)} method.
|
||||||
*
|
*
|
||||||
* <p>Here is an example of how this annotation is meant to be used:</p>
|
* <p>Here is an example of how this annotation is meant to be used:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class User {
|
* public class User {
|
||||||
* private String firstName;
|
* private String firstName;
|
||||||
* private String lastName;
|
* private String lastName;
|
||||||
* @Since(1.0) private String emailAddress;
|
* @Since(1.0) private String emailAddress;
|
||||||
* @Since(1.0) private String password;
|
* @Since(1.0) private String password;
|
||||||
* @Since(1.1) private Address address;
|
* @Since(1.1) private Address address;
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
|
* <p>If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
|
||||||
* methods will use all the fields for serialization and deserialization. However, if you created
|
* methods will use all the fields for serialization and deserialization. However, if you created
|
||||||
* Gson with {@code Gson gson = new GsonBuilder().setVersion(1.0).create()} then the
|
* Gson with {@code Gson gson = new GsonBuilder().setVersion(1.0).create()} then the
|
||||||
* {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code address} field
|
* {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code address} field
|
||||||
* since it's version number is set to {@code 1.1}.</p>
|
* since it's version number is set to {@code 1.1}.</p>
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||||
public @interface Since {
|
public @interface Since {
|
||||||
/**
|
/**
|
||||||
* the value indicating a version number since this member
|
* the value indicating a version number since this member
|
||||||
* or type has been present.
|
* or type has been present.
|
||||||
*/
|
*/
|
||||||
double value();
|
double value();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,66 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.annotations;
|
package com.google.gson.annotations;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An annotation that indicates the version number until a member or a type should be present.
|
* An annotation that indicates the version number until a member or a type should be present.
|
||||||
* Basically, if Gson is created with a version number that exceeds the value stored in the
|
* Basically, if Gson is created with a version number that exceeds the value stored in the
|
||||||
* {@code Until} annotation then the field will be ignored from the JSON output. This annotation
|
* {@code Until} annotation then the field will be ignored from the JSON output. This annotation
|
||||||
* is useful to manage versioning of your JSON classes for a web-service.
|
* is useful to manage versioning of your JSON classes for a web-service.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This annotation has no effect unless you build {@link com.google.gson.Gson} with a
|
* This annotation has no effect unless you build {@link com.google.gson.Gson} with a
|
||||||
* {@link com.google.gson.GsonBuilder} and invoke
|
* {@link com.google.gson.GsonBuilder} and invoke
|
||||||
* {@link com.google.gson.GsonBuilder#setVersion(double)} method.
|
* {@link com.google.gson.GsonBuilder#setVersion(double)} method.
|
||||||
*
|
*
|
||||||
* <p>Here is an example of how this annotation is meant to be used:</p>
|
* <p>Here is an example of how this annotation is meant to be used:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class User {
|
* public class User {
|
||||||
* private String firstName;
|
* private String firstName;
|
||||||
* private String lastName;
|
* private String lastName;
|
||||||
* @Until(1.1) private String emailAddress;
|
* @Until(1.1) private String emailAddress;
|
||||||
* @Until(1.1) private String password;
|
* @Until(1.1) private String password;
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
|
* <p>If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
|
||||||
* methods will use all the fields for serialization and deserialization. However, if you created
|
* methods will use all the fields for serialization and deserialization. However, if you created
|
||||||
* Gson with {@code Gson gson = new GsonBuilder().setVersion(1.2).create()} then the
|
* Gson with {@code Gson gson = new GsonBuilder().setVersion(1.2).create()} then the
|
||||||
* {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code emailAddress}
|
* {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code emailAddress}
|
||||||
* and {@code password} fields from the example above, because the version number passed to the
|
* and {@code password} fields from the example above, because the version number passed to the
|
||||||
* GsonBuilder, {@code 1.2}, exceeds the version number set on the {@code Until} annotation,
|
* GsonBuilder, {@code 1.2}, exceeds the version number set on the {@code Until} annotation,
|
||||||
* {@code 1.1}, for those fields.
|
* {@code 1.1}, for those fields.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
* @since 1.3
|
* @since 1.3
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||||
public @interface Until {
|
public @interface Until {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the value indicating a version number until this member
|
* the value indicating a version number until this member
|
||||||
* or type should be ignored.
|
* or type should be ignored.
|
||||||
*/
|
*/
|
||||||
double value();
|
double value();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* This package provides annotations that can be used with {@link com.google.gson.Gson}.
|
* This package provides annotations that can be used with {@link com.google.gson.Gson}.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh, Joel Leitch
|
* @author Inderjeet Singh, Joel Leitch
|
||||||
*/
|
*/
|
||||||
package com.google.gson.annotations;
|
package com.google.gson.annotations;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,176 +1,176 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import com.google.gson.InstanceCreator;
|
import com.google.gson.InstanceCreator;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a function that can construct an instance of a requested type.
|
* Returns a function that can construct an instance of a requested type.
|
||||||
*/
|
*/
|
||||||
public final class ConstructorConstructor {
|
public final class ConstructorConstructor {
|
||||||
private final Map<Type, InstanceCreator<?>> instanceCreators;
|
private final Map<Type, InstanceCreator<?>> instanceCreators;
|
||||||
|
|
||||||
public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) {
|
public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) {
|
||||||
this.instanceCreators = instanceCreators;
|
this.instanceCreators = instanceCreators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstructorConstructor() {
|
public ConstructorConstructor() {
|
||||||
this(Collections.<Type, InstanceCreator<?>>emptyMap());
|
this(Collections.<Type, InstanceCreator<?>>emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> ObjectConstructor<T> getConstructor(TypeToken<T> typeToken) {
|
public <T> ObjectConstructor<T> getConstructor(TypeToken<T> typeToken) {
|
||||||
final Type type = typeToken.getType();
|
final Type type = typeToken.getType();
|
||||||
final Class<? super T> rawType = typeToken.getRawType();
|
final Class<? super T> rawType = typeToken.getRawType();
|
||||||
|
|
||||||
// first try an instance creator
|
// first try an instance creator
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") // types must agree
|
@SuppressWarnings("unchecked") // types must agree
|
||||||
final InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreators.get(type);
|
final InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreators.get(type);
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
public T construct() {
|
||||||
return creator.createInstance(type);
|
return creator.createInstance(type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
|
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
|
||||||
if (defaultConstructor != null) {
|
if (defaultConstructor != null) {
|
||||||
return defaultConstructor;
|
return defaultConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(rawType);
|
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(rawType);
|
||||||
if (defaultImplementation != null) {
|
if (defaultImplementation != null) {
|
||||||
return defaultImplementation;
|
return defaultImplementation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally try unsafe
|
// finally try unsafe
|
||||||
return newUnsafeAllocator(type, rawType);
|
return newUnsafeAllocator(type, rawType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
|
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
|
||||||
try {
|
try {
|
||||||
final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
|
final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
|
||||||
if (!constructor.isAccessible()) {
|
if (!constructor.isAccessible()) {
|
||||||
constructor.setAccessible(true);
|
constructor.setAccessible(true);
|
||||||
}
|
}
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
@SuppressWarnings("unchecked") // T is the same raw type as is requested
|
@SuppressWarnings("unchecked") // T is the same raw type as is requested
|
||||||
public T construct() {
|
public T construct() {
|
||||||
try {
|
try {
|
||||||
Object[] args = null;
|
Object[] args = null;
|
||||||
return (T) constructor.newInstance(args);
|
return (T) constructor.newInstance(args);
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException e) {
|
||||||
// TODO: JsonParseException ?
|
// TODO: JsonParseException ?
|
||||||
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
|
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
// TODO: don't wrap if cause is unchecked!
|
// TODO: don't wrap if cause is unchecked!
|
||||||
// TODO: JsonParseException ?
|
// TODO: JsonParseException ?
|
||||||
throw new RuntimeException("Failed to invoke " + constructor + " with no args",
|
throw new RuntimeException("Failed to invoke " + constructor + " with no args",
|
||||||
e.getTargetException());
|
e.getTargetException());
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructors for common interface types like Map and List and their
|
* Constructors for common interface types like Map and List and their
|
||||||
* subytpes.
|
* subytpes.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked") // use runtime checks to guarantee that 'T' is what it is
|
@SuppressWarnings("unchecked") // use runtime checks to guarantee that 'T' is what it is
|
||||||
private <T> ObjectConstructor<T> newDefaultImplementationConstructor(Class<? super T> rawType) {
|
private <T> ObjectConstructor<T> newDefaultImplementationConstructor(Class<? super T> rawType) {
|
||||||
if (Collection.class.isAssignableFrom(rawType)) {
|
if (Collection.class.isAssignableFrom(rawType)) {
|
||||||
if (SortedSet.class.isAssignableFrom(rawType)) {
|
if (SortedSet.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
public T construct() {
|
||||||
return (T) new TreeSet<Object>();
|
return (T) new TreeSet<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (Set.class.isAssignableFrom(rawType)) {
|
} else if (Set.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
public T construct() {
|
||||||
return (T) new LinkedHashSet<Object>();
|
return (T) new LinkedHashSet<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (Queue.class.isAssignableFrom(rawType)) {
|
} else if (Queue.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
public T construct() {
|
||||||
return (T) new LinkedList<Object>();
|
return (T) new LinkedList<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
public T construct() {
|
||||||
return (T) new ArrayList<Object>();
|
return (T) new ArrayList<Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Map.class.isAssignableFrom(rawType)) {
|
if (Map.class.isAssignableFrom(rawType)) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
public T construct() {
|
public T construct() {
|
||||||
return (T) new LinkedHashMap<Object, Object>();
|
return (T) new LinkedHashMap<Object, Object>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// TODO: SortedMap ?
|
// TODO: SortedMap ?
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> ObjectConstructor<T> newUnsafeAllocator(
|
private <T> ObjectConstructor<T> newUnsafeAllocator(
|
||||||
final Type type, final Class<? super T> rawType) {
|
final Type type, final Class<? super T> rawType) {
|
||||||
return new ObjectConstructor<T>() {
|
return new ObjectConstructor<T>() {
|
||||||
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T construct() {
|
public T construct() {
|
||||||
try {
|
try {
|
||||||
Object newInstance = unsafeAllocator.newInstance(rawType);
|
Object newInstance = unsafeAllocator.newInstance(rawType);
|
||||||
return (T) newInstance;
|
return (T) newInstance;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". "
|
throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". "
|
||||||
+ "Register an InstanceCreator with Gson for this type may fix this problem."), e);
|
+ "Register an InstanceCreator with Gson for this type may fix this problem."), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
return instanceCreators.toString();
|
return instanceCreators.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,251 +1,251 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import com.google.gson.ExclusionStrategy;
|
import com.google.gson.ExclusionStrategy;
|
||||||
import com.google.gson.FieldAttributes;
|
import com.google.gson.FieldAttributes;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.annotations.Expose;
|
import com.google.gson.annotations.Expose;
|
||||||
import com.google.gson.annotations.Since;
|
import com.google.gson.annotations.Since;
|
||||||
import com.google.gson.annotations.Until;
|
import com.google.gson.annotations.Until;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class selects which fields and types to omit. It is configurable,
|
* This class selects which fields and types to omit. It is configurable,
|
||||||
* supporting version attributes {@link Since} and {@link Until}, modifiers,
|
* supporting version attributes {@link Since} and {@link Until}, modifiers,
|
||||||
* synthetic fields, anonymous and local classes, inner classes, and fields with
|
* synthetic fields, anonymous and local classes, inner classes, and fields with
|
||||||
* the {@link Expose} annotation.
|
* the {@link Expose} annotation.
|
||||||
*
|
*
|
||||||
* <p>This class is a type adapter factory; types that are excluded will be
|
* <p>This class is a type adapter factory; types that are excluded will be
|
||||||
* adapted to null. It may delegate to another type adapter if only one
|
* adapted to null. It may delegate to another type adapter if only one
|
||||||
* direction is excluded.
|
* direction is excluded.
|
||||||
*
|
*
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
*/
|
*/
|
||||||
public final class Excluder implements TypeAdapterFactory, Cloneable {
|
public final class Excluder implements TypeAdapterFactory, Cloneable {
|
||||||
private static final double IGNORE_VERSIONS = -1.0d;
|
private static final double IGNORE_VERSIONS = -1.0d;
|
||||||
public static final Excluder DEFAULT = new Excluder();
|
public static final Excluder DEFAULT = new Excluder();
|
||||||
|
|
||||||
private double version = IGNORE_VERSIONS;
|
private double version = IGNORE_VERSIONS;
|
||||||
private int modifiers = Modifier.TRANSIENT | Modifier.STATIC;
|
private int modifiers = Modifier.TRANSIENT | Modifier.STATIC;
|
||||||
private boolean serializeInnerClasses = true;
|
private boolean serializeInnerClasses = true;
|
||||||
private boolean requireExpose;
|
private boolean requireExpose;
|
||||||
private List<ExclusionStrategy> serializationStrategies = Collections.emptyList();
|
private List<ExclusionStrategy> serializationStrategies = Collections.emptyList();
|
||||||
private List<ExclusionStrategy> deserializationStrategies = Collections.emptyList();
|
private List<ExclusionStrategy> deserializationStrategies = Collections.emptyList();
|
||||||
|
|
||||||
@Override protected Excluder clone() {
|
@Override protected Excluder clone() {
|
||||||
try {
|
try {
|
||||||
return (Excluder) super.clone();
|
return (Excluder) super.clone();
|
||||||
} catch (CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Excluder withVersion(double ignoreVersionsAfter) {
|
public Excluder withVersion(double ignoreVersionsAfter) {
|
||||||
Excluder result = clone();
|
Excluder result = clone();
|
||||||
result.version = ignoreVersionsAfter;
|
result.version = ignoreVersionsAfter;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Excluder withModifiers(int... modifiers) {
|
public Excluder withModifiers(int... modifiers) {
|
||||||
Excluder result = clone();
|
Excluder result = clone();
|
||||||
result.modifiers = 0;
|
result.modifiers = 0;
|
||||||
for (int modifier : modifiers) {
|
for (int modifier : modifiers) {
|
||||||
result.modifiers |= modifier;
|
result.modifiers |= modifier;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Excluder disableInnerClassSerialization() {
|
public Excluder disableInnerClassSerialization() {
|
||||||
Excluder result = clone();
|
Excluder result = clone();
|
||||||
result.serializeInnerClasses = false;
|
result.serializeInnerClasses = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Excluder excludeFieldsWithoutExposeAnnotation() {
|
public Excluder excludeFieldsWithoutExposeAnnotation() {
|
||||||
Excluder result = clone();
|
Excluder result = clone();
|
||||||
result.requireExpose = true;
|
result.requireExpose = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy,
|
public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy,
|
||||||
boolean serialization, boolean deserialization) {
|
boolean serialization, boolean deserialization) {
|
||||||
Excluder result = clone();
|
Excluder result = clone();
|
||||||
if (serialization) {
|
if (serialization) {
|
||||||
result.serializationStrategies = new ArrayList<ExclusionStrategy>(serializationStrategies);
|
result.serializationStrategies = new ArrayList<ExclusionStrategy>(serializationStrategies);
|
||||||
result.serializationStrategies.add(exclusionStrategy);
|
result.serializationStrategies.add(exclusionStrategy);
|
||||||
}
|
}
|
||||||
if (deserialization) {
|
if (deserialization) {
|
||||||
result.deserializationStrategies
|
result.deserializationStrategies
|
||||||
= new ArrayList<ExclusionStrategy>(deserializationStrategies);
|
= new ArrayList<ExclusionStrategy>(deserializationStrategies);
|
||||||
result.deserializationStrategies.add(exclusionStrategy);
|
result.deserializationStrategies.add(exclusionStrategy);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
|
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
|
||||||
Class<?> rawType = type.getRawType();
|
Class<?> rawType = type.getRawType();
|
||||||
final boolean skipSerialize = excludeClass(rawType, true);
|
final boolean skipSerialize = excludeClass(rawType, true);
|
||||||
final boolean skipDeserialize = excludeClass(rawType, false);
|
final boolean skipDeserialize = excludeClass(rawType, false);
|
||||||
|
|
||||||
if (!skipSerialize && !skipDeserialize) {
|
if (!skipSerialize && !skipDeserialize) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TypeAdapter<T>() {
|
return new TypeAdapter<T>() {
|
||||||
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
|
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
|
||||||
private TypeAdapter<T> delegate;
|
private TypeAdapter<T> delegate;
|
||||||
|
|
||||||
@Override public T read(JsonReader in) throws IOException {
|
@Override public T read(JsonReader in) throws IOException {
|
||||||
if (skipDeserialize) {
|
if (skipDeserialize) {
|
||||||
in.skipValue();
|
in.skipValue();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return delegate().read(in);
|
return delegate().read(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void write(JsonWriter out, T value) throws IOException {
|
@Override public void write(JsonWriter out, T value) throws IOException {
|
||||||
if (skipSerialize) {
|
if (skipSerialize) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delegate().write(out, value);
|
delegate().write(out, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeAdapter<T> delegate() {
|
private TypeAdapter<T> delegate() {
|
||||||
TypeAdapter<T> d = delegate;
|
TypeAdapter<T> d = delegate;
|
||||||
return d != null
|
return d != null
|
||||||
? d
|
? d
|
||||||
: (delegate = GsonInternalAccess.INSTANCE.getNextAdapter(gson, Excluder.this, type));
|
: (delegate = GsonInternalAccess.INSTANCE.getNextAdapter(gson, Excluder.this, type));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean excludeField(Field field, boolean serialize) {
|
public boolean excludeField(Field field, boolean serialize) {
|
||||||
if ((modifiers & field.getModifiers()) != 0) {
|
if ((modifiers & field.getModifiers()) != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version != Excluder.IGNORE_VERSIONS
|
if (version != Excluder.IGNORE_VERSIONS
|
||||||
&& !isValidVersion(field.getAnnotation(Since.class), field.getAnnotation(Until.class))) {
|
&& !isValidVersion(field.getAnnotation(Since.class), field.getAnnotation(Until.class))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field.isSynthetic()) {
|
if (field.isSynthetic()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requireExpose) {
|
if (requireExpose) {
|
||||||
Expose annotation = field.getAnnotation(Expose.class);
|
Expose annotation = field.getAnnotation(Expose.class);
|
||||||
if (annotation == null || (serialize ? !annotation.serialize() : !annotation.deserialize())) {
|
if (annotation == null || (serialize ? !annotation.serialize() : !annotation.deserialize())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!serializeInnerClasses && isInnerClass(field.getType())) {
|
if (!serializeInnerClasses && isInnerClass(field.getType())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAnonymousOrLocal(field.getType())) {
|
if (isAnonymousOrLocal(field.getType())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
|
List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
|
||||||
if (!list.isEmpty()) {
|
if (!list.isEmpty()) {
|
||||||
FieldAttributes fieldAttributes = new FieldAttributes(field);
|
FieldAttributes fieldAttributes = new FieldAttributes(field);
|
||||||
for (ExclusionStrategy exclusionStrategy : list) {
|
for (ExclusionStrategy exclusionStrategy : list) {
|
||||||
if (exclusionStrategy.shouldSkipField(fieldAttributes)) {
|
if (exclusionStrategy.shouldSkipField(fieldAttributes)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean excludeClass(Class<?> clazz, boolean serialize) {
|
public boolean excludeClass(Class<?> clazz, boolean serialize) {
|
||||||
if (version != Excluder.IGNORE_VERSIONS
|
if (version != Excluder.IGNORE_VERSIONS
|
||||||
&& !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) {
|
&& !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!serializeInnerClasses && isInnerClass(clazz)) {
|
if (!serializeInnerClasses && isInnerClass(clazz)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAnonymousOrLocal(clazz)) {
|
if (isAnonymousOrLocal(clazz)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
|
List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
|
||||||
for (ExclusionStrategy exclusionStrategy : list) {
|
for (ExclusionStrategy exclusionStrategy : list) {
|
||||||
if (exclusionStrategy.shouldSkipClass(clazz)) {
|
if (exclusionStrategy.shouldSkipClass(clazz)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAnonymousOrLocal(Class<?> clazz) {
|
private boolean isAnonymousOrLocal(Class<?> clazz) {
|
||||||
return !Enum.class.isAssignableFrom(clazz)
|
return !Enum.class.isAssignableFrom(clazz)
|
||||||
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
|
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInnerClass(Class<?> clazz) {
|
private boolean isInnerClass(Class<?> clazz) {
|
||||||
return clazz.isMemberClass() && !isStatic(clazz);
|
return clazz.isMemberClass() && !isStatic(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStatic(Class<?> clazz) {
|
private boolean isStatic(Class<?> clazz) {
|
||||||
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
return (clazz.getModifiers() & Modifier.STATIC) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidVersion(Since since, Until until) {
|
private boolean isValidVersion(Since since, Until until) {
|
||||||
return isValidSince(since) && isValidUntil(until);
|
return isValidSince(since) && isValidUntil(until);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidSince(Since annotation) {
|
private boolean isValidSince(Since annotation) {
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
double annotationVersion = annotation.value();
|
double annotationVersion = annotation.value();
|
||||||
if (annotationVersion > version) {
|
if (annotationVersion > version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidUntil(Until annotation) {
|
private boolean isValidUntil(Until annotation) {
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
double annotationVersion = annotation.value();
|
double annotationVersion = annotation.value();
|
||||||
if (annotationVersion <= version) {
|
if (annotationVersion <= version) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal-only APIs of Gson available only to other classes in Gson.
|
* Internal-only APIs of Gson available only to other classes in Gson.
|
||||||
*/
|
*/
|
||||||
public abstract class GsonInternalAccess {
|
public abstract class GsonInternalAccess {
|
||||||
public static GsonInternalAccess INSTANCE;
|
public static GsonInternalAccess INSTANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a type adapter for {@code} type that isn't {@code skipPast}. This
|
* Returns a type adapter for {@code} type that isn't {@code skipPast}. This
|
||||||
* can be used for type adapters to compose other, simpler type adapters.
|
* can be used for type adapters to compose other, simpler type adapters.
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException if this GSON cannot serialize and
|
* @throws IllegalArgumentException if this GSON cannot serialize and
|
||||||
* deserialize {@code type}.
|
* deserialize {@code type}.
|
||||||
*/
|
*/
|
||||||
public abstract <T> TypeAdapter<T> getNextAdapter(
|
public abstract <T> TypeAdapter<T> getNextAdapter(
|
||||||
Gson gson, TypeAdapterFactory skipPast, TypeToken<T> type);
|
Gson gson, TypeAdapterFactory skipPast, TypeToken<T> type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal-only APIs of JsonReader available only to other classes in Gson.
|
* Internal-only APIs of JsonReader available only to other classes in Gson.
|
||||||
*/
|
*/
|
||||||
public abstract class JsonReaderInternalAccess {
|
public abstract class JsonReaderInternalAccess {
|
||||||
public static JsonReaderInternalAccess INSTANCE;
|
public static JsonReaderInternalAccess INSTANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the type of the current property name token to a string value.
|
* Changes the type of the current property name token to a string value.
|
||||||
*/
|
*/
|
||||||
public abstract void promoteNameToValue(JsonReader reader) throws IOException;
|
public abstract void promoteNameToValue(JsonReader reader) throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds a number value that is lazily converted to a specific number type
|
* This class holds a number value that is lazily converted to a specific number type
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public final class LazilyParsedNumber extends Number {
|
public final class LazilyParsedNumber extends Number {
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
public LazilyParsedNumber(String value) {
|
public LazilyParsedNumber(String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int intValue() {
|
public int intValue() {
|
||||||
try {
|
try {
|
||||||
return Integer.parseInt(value);
|
return Integer.parseInt(value);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
try {
|
try {
|
||||||
return (int) Long.parseLong(value);
|
return (int) Long.parseLong(value);
|
||||||
} catch (NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
return new BigInteger(value).intValue();
|
return new BigInteger(value).intValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long longValue() {
|
public long longValue() {
|
||||||
try {
|
try {
|
||||||
return Long.parseLong(value);
|
return Long.parseLong(value);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return new BigInteger(value).longValue();
|
return new BigInteger(value).longValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float floatValue() {
|
public float floatValue() {
|
||||||
return Float.parseFloat(value);
|
return Float.parseFloat(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double doubleValue() {
|
public double doubleValue() {
|
||||||
return Double.parseDouble(value);
|
return Double.parseDouble(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a generic object construction factory. The purpose of this class
|
* Defines a generic object construction factory. The purpose of this class
|
||||||
* is to construct a default instance of a class that can be used for object
|
* is to construct a default instance of a class that can be used for object
|
||||||
* navigation while deserialization from its JSON representation.
|
* navigation while deserialization from its JSON representation.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public interface ObjectConstructor<T> {
|
public interface ObjectConstructor<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new instance.
|
* Returns a new instance.
|
||||||
*/
|
*/
|
||||||
public T construct();
|
public T construct();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Google Inc.
|
* Copyright (C) 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple object that holds onto a pair of object references, first and second.
|
* A simple object that holds onto a pair of object references, first and second.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*
|
*
|
||||||
* @param <FIRST>
|
* @param <FIRST>
|
||||||
* @param <SECOND>
|
* @param <SECOND>
|
||||||
*/
|
*/
|
||||||
public final class Pair<FIRST, SECOND> {
|
public final class Pair<FIRST, SECOND> {
|
||||||
public final FIRST first;
|
public final FIRST first;
|
||||||
public final SECOND second;
|
public final SECOND second;
|
||||||
|
|
||||||
public Pair(FIRST first, SECOND second) {
|
public Pair(FIRST first, SECOND second) {
|
||||||
this.first = first;
|
this.first = first;
|
||||||
this.second = second;
|
this.second = second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return 17 * ((first != null) ? first.hashCode() : 0)
|
return 17 * ((first != null) ? first.hashCode() : 0)
|
||||||
+ 17 * ((second != null) ? second.hashCode() : 0);
|
+ 17 * ((second != null) ? second.hashCode() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof Pair<?, ?>)) {
|
if (!(o instanceof Pair<?, ?>)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<?, ?> that = (Pair<?, ?>) o;
|
Pair<?, ?> that = (Pair<?, ?>) o;
|
||||||
return equal(this.first, that.first) && equal(this.second, that.second);
|
return equal(this.first, that.first) && equal(this.second, that.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean equal(Object a, Object b) {
|
private static boolean equal(Object a, Object b) {
|
||||||
return a == b || (a != null && a.equals(b));
|
return a == b || (a != null && a.equals(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("{%s,%s}", first, second);
|
return String.format("{%s,%s}", first, second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,118 +1,118 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains static utility methods pertaining to primitive types and their
|
* Contains static utility methods pertaining to primitive types and their
|
||||||
* corresponding wrapper types.
|
* corresponding wrapper types.
|
||||||
*
|
*
|
||||||
* @author Kevin Bourrillion
|
* @author Kevin Bourrillion
|
||||||
*/
|
*/
|
||||||
public final class Primitives {
|
public final class Primitives {
|
||||||
private Primitives() {}
|
private Primitives() {}
|
||||||
|
|
||||||
/** A map from primitive types to their corresponding wrapper types. */
|
/** A map from primitive types to their corresponding wrapper types. */
|
||||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
|
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
|
||||||
|
|
||||||
/** A map from wrapper types to their corresponding primitive types. */
|
/** A map from wrapper types to their corresponding primitive types. */
|
||||||
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
|
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
|
||||||
|
|
||||||
// Sad that we can't use a BiMap. :(
|
// Sad that we can't use a BiMap. :(
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
|
Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
|
||||||
Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
|
Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
|
||||||
|
|
||||||
add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
|
add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
|
||||||
add(primToWrap, wrapToPrim, byte.class, Byte.class);
|
add(primToWrap, wrapToPrim, byte.class, Byte.class);
|
||||||
add(primToWrap, wrapToPrim, char.class, Character.class);
|
add(primToWrap, wrapToPrim, char.class, Character.class);
|
||||||
add(primToWrap, wrapToPrim, double.class, Double.class);
|
add(primToWrap, wrapToPrim, double.class, Double.class);
|
||||||
add(primToWrap, wrapToPrim, float.class, Float.class);
|
add(primToWrap, wrapToPrim, float.class, Float.class);
|
||||||
add(primToWrap, wrapToPrim, int.class, Integer.class);
|
add(primToWrap, wrapToPrim, int.class, Integer.class);
|
||||||
add(primToWrap, wrapToPrim, long.class, Long.class);
|
add(primToWrap, wrapToPrim, long.class, Long.class);
|
||||||
add(primToWrap, wrapToPrim, short.class, Short.class);
|
add(primToWrap, wrapToPrim, short.class, Short.class);
|
||||||
add(primToWrap, wrapToPrim, void.class, Void.class);
|
add(primToWrap, wrapToPrim, void.class, Void.class);
|
||||||
|
|
||||||
PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
|
PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
|
||||||
WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
|
WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void add(Map<Class<?>, Class<?>> forward,
|
private static void add(Map<Class<?>, Class<?>> forward,
|
||||||
Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
|
Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
|
||||||
forward.put(key, value);
|
forward.put(key, value);
|
||||||
backward.put(value, key);
|
backward.put(value, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this type is a primitive.
|
* Returns true if this type is a primitive.
|
||||||
*/
|
*/
|
||||||
public static boolean isPrimitive(Type type) {
|
public static boolean isPrimitive(Type type) {
|
||||||
return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type);
|
return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if {@code type} is one of the nine
|
* Returns {@code true} if {@code type} is one of the nine
|
||||||
* primitive-wrapper types, such as {@link Integer}.
|
* primitive-wrapper types, such as {@link Integer}.
|
||||||
*
|
*
|
||||||
* @see Class#isPrimitive
|
* @see Class#isPrimitive
|
||||||
*/
|
*/
|
||||||
public static boolean isWrapperType(Type type) {
|
public static boolean isWrapperType(Type type) {
|
||||||
return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(
|
return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(
|
||||||
$Gson$Preconditions.checkNotNull(type));
|
$Gson$Preconditions.checkNotNull(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the corresponding wrapper type of {@code type} if it is a primitive
|
* Returns the corresponding wrapper type of {@code type} if it is a primitive
|
||||||
* type; otherwise returns {@code type} itself. Idempotent.
|
* type; otherwise returns {@code type} itself. Idempotent.
|
||||||
* <pre>
|
* <pre>
|
||||||
* wrap(int.class) == Integer.class
|
* wrap(int.class) == Integer.class
|
||||||
* wrap(Integer.class) == Integer.class
|
* wrap(Integer.class) == Integer.class
|
||||||
* wrap(String.class) == String.class
|
* wrap(String.class) == String.class
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public static <T> Class<T> wrap(Class<T> type) {
|
public static <T> Class<T> wrap(Class<T> type) {
|
||||||
// cast is safe: long.class and Long.class are both of type Class<Long>
|
// cast is safe: long.class and Long.class are both of type Class<Long>
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(
|
Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(
|
||||||
$Gson$Preconditions.checkNotNull(type));
|
$Gson$Preconditions.checkNotNull(type));
|
||||||
return (wrapped == null) ? type : wrapped;
|
return (wrapped == null) ? type : wrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the corresponding primitive type of {@code type} if it is a
|
* Returns the corresponding primitive type of {@code type} if it is a
|
||||||
* wrapper type; otherwise returns {@code type} itself. Idempotent.
|
* wrapper type; otherwise returns {@code type} itself. Idempotent.
|
||||||
* <pre>
|
* <pre>
|
||||||
* unwrap(Integer.class) == int.class
|
* unwrap(Integer.class) == int.class
|
||||||
* unwrap(int.class) == int.class
|
* unwrap(int.class) == int.class
|
||||||
* unwrap(String.class) == String.class
|
* unwrap(String.class) == String.class
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public static <T> Class<T> unwrap(Class<T> type) {
|
public static <T> Class<T> unwrap(Class<T> type) {
|
||||||
// cast is safe: long.class and Long.class are both of type Class<Long>
|
// cast is safe: long.class and Long.class are both of type Class<Long>
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE.get(
|
Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE.get(
|
||||||
$Gson$Preconditions.checkNotNull(type));
|
$Gson$Preconditions.checkNotNull(type));
|
||||||
return (unwrapped == null) ? type : unwrapped;
|
return (unwrapped == null) ? type : unwrapped;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +1,115 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Google Inc.
|
* Copyright (C) 2010 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonNull;
|
import com.google.gson.JsonNull;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.internal.bind.TypeAdapters;
|
import com.google.gson.internal.bind.TypeAdapters;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import com.google.gson.stream.MalformedJsonException;
|
import com.google.gson.stream.MalformedJsonException;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and writes GSON parse trees over streams.
|
* Reads and writes GSON parse trees over streams.
|
||||||
*/
|
*/
|
||||||
public final class Streams {
|
public final class Streams {
|
||||||
/**
|
/**
|
||||||
* Takes a reader in any state and returns the next value as a JsonElement.
|
* Takes a reader in any state and returns the next value as a JsonElement.
|
||||||
*/
|
*/
|
||||||
public static JsonElement parse(JsonReader reader) throws JsonParseException {
|
public static JsonElement parse(JsonReader reader) throws JsonParseException {
|
||||||
boolean isEmpty = true;
|
boolean isEmpty = true;
|
||||||
try {
|
try {
|
||||||
reader.peek();
|
reader.peek();
|
||||||
isEmpty = false;
|
isEmpty = false;
|
||||||
return TypeAdapters.JSON_ELEMENT.read(reader);
|
return TypeAdapters.JSON_ELEMENT.read(reader);
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
/*
|
/*
|
||||||
* For compatibility with JSON 1.5 and earlier, we return a JsonNull for
|
* For compatibility with JSON 1.5 and earlier, we return a JsonNull for
|
||||||
* empty documents instead of throwing.
|
* empty documents instead of throwing.
|
||||||
*/
|
*/
|
||||||
if (isEmpty) {
|
if (isEmpty) {
|
||||||
return JsonNull.INSTANCE;
|
return JsonNull.INSTANCE;
|
||||||
}
|
}
|
||||||
throw new JsonIOException(e);
|
throw new JsonIOException(e);
|
||||||
} catch (MalformedJsonException e) {
|
} catch (MalformedJsonException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JsonIOException(e);
|
throw new JsonIOException(e);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the JSON element to the writer, recursively.
|
* Writes the JSON element to the writer, recursively.
|
||||||
*/
|
*/
|
||||||
public static void write(JsonElement element, JsonWriter writer) throws IOException {
|
public static void write(JsonElement element, JsonWriter writer) throws IOException {
|
||||||
TypeAdapters.JSON_ELEMENT.write(writer, element);
|
TypeAdapters.JSON_ELEMENT.write(writer, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Writer writerForAppendable(Appendable appendable) {
|
public static Writer writerForAppendable(Appendable appendable) {
|
||||||
return appendable instanceof Writer ? (Writer) appendable : new AppendableWriter(appendable);
|
return appendable instanceof Writer ? (Writer) appendable : new AppendableWriter(appendable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts an {@link Appendable} so it can be passed anywhere a {@link Writer}
|
* Adapts an {@link Appendable} so it can be passed anywhere a {@link Writer}
|
||||||
* is used.
|
* is used.
|
||||||
*/
|
*/
|
||||||
private static class AppendableWriter extends Writer {
|
private static class AppendableWriter extends Writer {
|
||||||
private final Appendable appendable;
|
private final Appendable appendable;
|
||||||
private final CurrentWrite currentWrite = new CurrentWrite();
|
private final CurrentWrite currentWrite = new CurrentWrite();
|
||||||
|
|
||||||
private AppendableWriter(Appendable appendable) {
|
private AppendableWriter(Appendable appendable) {
|
||||||
this.appendable = appendable;
|
this.appendable = appendable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void write(char[] chars, int offset, int length) throws IOException {
|
@Override public void write(char[] chars, int offset, int length) throws IOException {
|
||||||
currentWrite.chars = chars;
|
currentWrite.chars = chars;
|
||||||
appendable.append(currentWrite, offset, offset + length);
|
appendable.append(currentWrite, offset, offset + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void write(int i) throws IOException {
|
@Override public void write(int i) throws IOException {
|
||||||
appendable.append((char) i);
|
appendable.append((char) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void flush() {}
|
@Override public void flush() {}
|
||||||
@Override public void close() {}
|
@Override public void close() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mutable char sequence pointing at a single char[].
|
* A mutable char sequence pointing at a single char[].
|
||||||
*/
|
*/
|
||||||
static class CurrentWrite implements CharSequence {
|
static class CurrentWrite implements CharSequence {
|
||||||
char[] chars;
|
char[] chars;
|
||||||
public int length() {
|
public int length() {
|
||||||
return chars.length;
|
return chars.length;
|
||||||
}
|
}
|
||||||
public char charAt(int i) {
|
public char charAt(int i) {
|
||||||
return chars[i];
|
return chars[i];
|
||||||
}
|
}
|
||||||
public CharSequence subSequence(int start, int end) {
|
public CharSequence subSequence(int start, int end) {
|
||||||
return new String(chars, start, end - start);
|
return new String(chars, start, end - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,104 +1,104 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectStreamClass;
|
import java.io.ObjectStreamClass;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do sneaky things to allocate objects without invoking their constructors.
|
* Do sneaky things to allocate objects without invoking their constructors.
|
||||||
*
|
*
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
*/
|
*/
|
||||||
public abstract class UnsafeAllocator {
|
public abstract class UnsafeAllocator {
|
||||||
public abstract <T> T newInstance(Class<T> c) throws Exception;
|
public abstract <T> T newInstance(Class<T> c) throws Exception;
|
||||||
|
|
||||||
public static UnsafeAllocator create() {
|
public static UnsafeAllocator create() {
|
||||||
// try JVM
|
// try JVM
|
||||||
// public class Unsafe {
|
// public class Unsafe {
|
||||||
// public Object allocateInstance(Class<?> type);
|
// public Object allocateInstance(Class<?> type);
|
||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
||||||
Field f = unsafeClass.getDeclaredField("theUnsafe");
|
Field f = unsafeClass.getDeclaredField("theUnsafe");
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
final Object unsafe = f.get(null);
|
final Object unsafe = f.get(null);
|
||||||
final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
|
final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
|
||||||
return new UnsafeAllocator() {
|
return new UnsafeAllocator() {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T newInstance(Class<T> c) throws Exception {
|
public <T> T newInstance(Class<T> c) throws Exception {
|
||||||
return (T) allocateInstance.invoke(unsafe, c);
|
return (T) allocateInstance.invoke(unsafe, c);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// try dalvikvm, pre-gingerbread
|
// try dalvikvm, pre-gingerbread
|
||||||
// public class ObjectInputStream {
|
// public class ObjectInputStream {
|
||||||
// private static native Object newInstance(
|
// private static native Object newInstance(
|
||||||
// Class<?> instantiationClass, Class<?> constructorClass);
|
// Class<?> instantiationClass, Class<?> constructorClass);
|
||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
final Method newInstance = ObjectInputStream.class
|
final Method newInstance = ObjectInputStream.class
|
||||||
.getDeclaredMethod("newInstance", Class.class, Class.class);
|
.getDeclaredMethod("newInstance", Class.class, Class.class);
|
||||||
newInstance.setAccessible(true);
|
newInstance.setAccessible(true);
|
||||||
return new UnsafeAllocator() {
|
return new UnsafeAllocator() {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T newInstance(Class<T> c) throws Exception {
|
public <T> T newInstance(Class<T> c) throws Exception {
|
||||||
return (T) newInstance.invoke(null, c, Object.class);
|
return (T) newInstance.invoke(null, c, Object.class);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// try dalvikvm, post-gingerbread
|
// try dalvikvm, post-gingerbread
|
||||||
// public class ObjectStreamClass {
|
// public class ObjectStreamClass {
|
||||||
// private static native int getConstructorId(Class<?> c);
|
// private static native int getConstructorId(Class<?> c);
|
||||||
// private static native Object newInstance(Class<?> instantiationClass, int methodId);
|
// private static native Object newInstance(Class<?> instantiationClass, int methodId);
|
||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
Method getConstructorId = ObjectStreamClass.class
|
Method getConstructorId = ObjectStreamClass.class
|
||||||
.getDeclaredMethod("getConstructorId", Class.class);
|
.getDeclaredMethod("getConstructorId", Class.class);
|
||||||
getConstructorId.setAccessible(true);
|
getConstructorId.setAccessible(true);
|
||||||
final int constructorId = (Integer) getConstructorId.invoke(null, Object.class);
|
final int constructorId = (Integer) getConstructorId.invoke(null, Object.class);
|
||||||
final Method newInstance = ObjectStreamClass.class
|
final Method newInstance = ObjectStreamClass.class
|
||||||
.getDeclaredMethod("newInstance", Class.class, int.class);
|
.getDeclaredMethod("newInstance", Class.class, int.class);
|
||||||
newInstance.setAccessible(true);
|
newInstance.setAccessible(true);
|
||||||
return new UnsafeAllocator() {
|
return new UnsafeAllocator() {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T newInstance(Class<T> c) throws Exception {
|
public <T> T newInstance(Class<T> c) throws Exception {
|
||||||
return (T) newInstance.invoke(null, c, constructorId);
|
return (T) newInstance.invoke(null, c, constructorId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// give up
|
// give up
|
||||||
return new UnsafeAllocator() {
|
return new UnsafeAllocator() {
|
||||||
@Override
|
@Override
|
||||||
public <T> T newInstance(Class<T> c) {
|
public <T> T newInstance(Class<T> c) {
|
||||||
throw new UnsupportedOperationException("Cannot allocate " + c);
|
throw new UnsupportedOperationException("Cannot allocate " + c);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +1,97 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.GenericArrayType;
|
import java.lang.reflect.GenericArrayType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapt an array of objects.
|
* Adapt an array of objects.
|
||||||
*/
|
*/
|
||||||
public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
|
public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
|
||||||
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
Type type = typeToken.getType();
|
Type type = typeToken.getType();
|
||||||
if (!(type instanceof GenericArrayType || type instanceof Class && ((Class<?>) type).isArray())) {
|
if (!(type instanceof GenericArrayType || type instanceof Class && ((Class<?>) type).isArray())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type componentType = $Gson$Types.getArrayComponentType(type);
|
Type componentType = $Gson$Types.getArrayComponentType(type);
|
||||||
TypeAdapter<?> componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType));
|
TypeAdapter<?> componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType));
|
||||||
return new ArrayTypeAdapter(
|
return new ArrayTypeAdapter(
|
||||||
gson, componentTypeAdapter, $Gson$Types.getRawType(componentType));
|
gson, componentTypeAdapter, $Gson$Types.getRawType(componentType));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Class<E> componentType;
|
private final Class<E> componentType;
|
||||||
private final TypeAdapter<E> componentTypeAdapter;
|
private final TypeAdapter<E> componentTypeAdapter;
|
||||||
|
|
||||||
public ArrayTypeAdapter(Gson context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) {
|
public ArrayTypeAdapter(Gson context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) {
|
||||||
this.componentTypeAdapter =
|
this.componentTypeAdapter =
|
||||||
new TypeAdapterRuntimeTypeWrapper<E>(context, componentTypeAdapter, componentType);
|
new TypeAdapterRuntimeTypeWrapper<E>(context, componentTypeAdapter, componentType);
|
||||||
this.componentType = componentType;
|
this.componentType = componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object read(JsonReader in) throws IOException {
|
public Object read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<E> list = new ArrayList<E>();
|
List<E> list = new ArrayList<E>();
|
||||||
in.beginArray();
|
in.beginArray();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
E instance = componentTypeAdapter.read(in);
|
E instance = componentTypeAdapter.read(in);
|
||||||
list.add(instance);
|
list.add(instance);
|
||||||
}
|
}
|
||||||
in.endArray();
|
in.endArray();
|
||||||
Object array = Array.newInstance(componentType, list.size());
|
Object array = Array.newInstance(componentType, list.size());
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
Array.set(array, i, list.get(i));
|
Array.set(array, i, list.get(i));
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override public void write(JsonWriter out, Object array) throws IOException {
|
@Override public void write(JsonWriter out, Object array) throws IOException {
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.beginArray();
|
out.beginArray();
|
||||||
for (int i = 0, length = Array.getLength(array); i < length; i++) {
|
for (int i = 0, length = Array.getLength(array); i < length; i++) {
|
||||||
E value = (E) Array.get(array, i);
|
E value = (E) Array.get(array, i);
|
||||||
componentTypeAdapter.write(out, value);
|
componentTypeAdapter.write(out, value);
|
||||||
}
|
}
|
||||||
out.endArray();
|
out.endArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts a BigDecimal type to and from its JSON representation.
|
* Adapts a BigDecimal type to and from its JSON representation.
|
||||||
*
|
*
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class BigDecimalTypeAdapter extends TypeAdapter<BigDecimal> {
|
public final class BigDecimalTypeAdapter extends TypeAdapter<BigDecimal> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal read(JsonReader in) throws IOException {
|
public BigDecimal read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new BigDecimal(in.nextString());
|
return new BigDecimal(in.nextString());
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, BigDecimal value) throws IOException {
|
public void write(JsonWriter out, BigDecimal value) throws IOException {
|
||||||
out.value(value);
|
out.value(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts a BigInteger type to and from its JSON representation.
|
* Adapts a BigInteger type to and from its JSON representation.
|
||||||
*
|
*
|
||||||
* @author Joel Leitch
|
* @author Joel Leitch
|
||||||
*/
|
*/
|
||||||
public final class BigIntegerTypeAdapter extends TypeAdapter<BigInteger> {
|
public final class BigIntegerTypeAdapter extends TypeAdapter<BigInteger> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigInteger read(JsonReader in) throws IOException {
|
public BigInteger read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new BigInteger(in.nextString());
|
return new BigInteger(in.nextString());
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, BigInteger value) throws IOException {
|
public void write(JsonWriter out, BigInteger value) throws IOException {
|
||||||
out.value(value);
|
out.value(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +1,101 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
import com.google.gson.internal.ConstructorConstructor;
|
import com.google.gson.internal.ConstructorConstructor;
|
||||||
import com.google.gson.internal.ObjectConstructor;
|
import com.google.gson.internal.ObjectConstructor;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapt a homogeneous collection of objects.
|
* Adapt a homogeneous collection of objects.
|
||||||
*/
|
*/
|
||||||
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
|
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
|
||||||
private final ConstructorConstructor constructorConstructor;
|
private final ConstructorConstructor constructorConstructor;
|
||||||
|
|
||||||
public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
|
public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
|
||||||
this.constructorConstructor = constructorConstructor;
|
this.constructorConstructor = constructorConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
Type type = typeToken.getType();
|
Type type = typeToken.getType();
|
||||||
|
|
||||||
Class<? super T> rawType = typeToken.getRawType();
|
Class<? super T> rawType = typeToken.getRawType();
|
||||||
if (!Collection.class.isAssignableFrom(rawType)) {
|
if (!Collection.class.isAssignableFrom(rawType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
|
Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
|
||||||
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
|
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
|
||||||
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(typeToken);
|
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(typeToken);
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
|
@SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
|
||||||
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
|
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class Adapter<E> extends TypeAdapter<Collection<E>> {
|
private final class Adapter<E> extends TypeAdapter<Collection<E>> {
|
||||||
private final TypeAdapter<E> elementTypeAdapter;
|
private final TypeAdapter<E> elementTypeAdapter;
|
||||||
private final ObjectConstructor<? extends Collection<E>> constructor;
|
private final ObjectConstructor<? extends Collection<E>> constructor;
|
||||||
|
|
||||||
public Adapter(Gson context, Type elementType,
|
public Adapter(Gson context, Type elementType,
|
||||||
TypeAdapter<E> elementTypeAdapter,
|
TypeAdapter<E> elementTypeAdapter,
|
||||||
ObjectConstructor<? extends Collection<E>> constructor) {
|
ObjectConstructor<? extends Collection<E>> constructor) {
|
||||||
this.elementTypeAdapter =
|
this.elementTypeAdapter =
|
||||||
new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
|
new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<E> read(JsonReader in) throws IOException {
|
public Collection<E> read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<E> collection = constructor.construct();
|
Collection<E> collection = constructor.construct();
|
||||||
in.beginArray();
|
in.beginArray();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
E instance = elementTypeAdapter.read(in);
|
E instance = elementTypeAdapter.read(in);
|
||||||
collection.add(instance);
|
collection.add(instance);
|
||||||
}
|
}
|
||||||
in.endArray();
|
in.endArray();
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(JsonWriter out, Collection<E> collection) throws IOException {
|
public void write(JsonWriter out, Collection<E> collection) throws IOException {
|
||||||
if (collection == null) {
|
if (collection == null) {
|
||||||
out.nullValue(); // TODO: better policy here?
|
out.nullValue(); // TODO: better policy here?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.beginArray();
|
out.beginArray();
|
||||||
for (E element : collection) {
|
for (E element : collection) {
|
||||||
elementTypeAdapter.write(out, element);
|
elementTypeAdapter.write(out, element);
|
||||||
}
|
}
|
||||||
out.endArray();
|
out.endArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,93 +1,93 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for Date. Although this class appears stateless, it is not.
|
* Adapter for Date. Although this class appears stateless, it is not.
|
||||||
* DateFormat captures its time zone and locale when it is created, which gives
|
* DateFormat captures its time zone and locale when it is created, which gives
|
||||||
* this class state. DateFormat isn't thread safe either, so this class has
|
* this class state. DateFormat isn't thread safe either, so this class has
|
||||||
* to synchronize its read and write methods.
|
* to synchronize its read and write methods.
|
||||||
*/
|
*/
|
||||||
public final class DateTypeAdapter extends TypeAdapter<Date> {
|
public final class DateTypeAdapter extends TypeAdapter<Date> {
|
||||||
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
||||||
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null;
|
return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final DateFormat enUsFormat
|
private final DateFormat enUsFormat
|
||||||
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);
|
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);
|
||||||
private final DateFormat localFormat
|
private final DateFormat localFormat
|
||||||
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);
|
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);
|
||||||
private final DateFormat iso8601Format = buildIso8601Format();
|
private final DateFormat iso8601Format = buildIso8601Format();
|
||||||
|
|
||||||
private static DateFormat buildIso8601Format() {
|
private static DateFormat buildIso8601Format() {
|
||||||
DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||||
iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
return iso8601Format;
|
return iso8601Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Date read(JsonReader in) throws IOException {
|
@Override public Date read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return deserializeToDate(in.nextString());
|
return deserializeToDate(in.nextString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized Date deserializeToDate(String json) {
|
private synchronized Date deserializeToDate(String json) {
|
||||||
try {
|
try {
|
||||||
return localFormat.parse(json);
|
return localFormat.parse(json);
|
||||||
} catch (ParseException ignored) {
|
} catch (ParseException ignored) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return enUsFormat.parse(json);
|
return enUsFormat.parse(json);
|
||||||
} catch (ParseException ignored) {
|
} catch (ParseException ignored) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return iso8601Format.parse(json);
|
return iso8601Format.parse(json);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(json, e);
|
throw new JsonSyntaxException(json, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public synchronized void write(JsonWriter out, Date value) throws IOException {
|
@Override public synchronized void write(JsonWriter out, Date value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String dateFormatAsString = enUsFormat.format(value);
|
String dateFormatAsString = enUsFormat.format(value);
|
||||||
out.value(dateFormatAsString);
|
out.value(dateFormatAsString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,226 +1,226 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonNull;
|
import com.google.gson.JsonNull;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This reader walks the elements of a JsonElement as if it was coming from a
|
* This reader walks the elements of a JsonElement as if it was coming from a
|
||||||
* character stream.
|
* character stream.
|
||||||
*
|
*
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
*/
|
*/
|
||||||
public final class JsonTreeReader extends JsonReader {
|
public final class JsonTreeReader extends JsonReader {
|
||||||
private static final Reader UNREADABLE_READER = new Reader() {
|
private static final Reader UNREADABLE_READER = new Reader() {
|
||||||
@Override public int read(char[] buffer, int offset, int count) throws IOException {
|
@Override public int read(char[] buffer, int offset, int count) throws IOException {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@Override public void close() throws IOException {
|
@Override public void close() throws IOException {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private static final Object SENTINEL_CLOSED = new Object();
|
private static final Object SENTINEL_CLOSED = new Object();
|
||||||
|
|
||||||
private final List<Object> stack = new ArrayList<Object>();
|
private final List<Object> stack = new ArrayList<Object>();
|
||||||
|
|
||||||
public JsonTreeReader(JsonElement element) {
|
public JsonTreeReader(JsonElement element) {
|
||||||
super(UNREADABLE_READER);
|
super(UNREADABLE_READER);
|
||||||
stack.add(element);
|
stack.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void beginArray() throws IOException {
|
@Override public void beginArray() throws IOException {
|
||||||
expect(JsonToken.BEGIN_ARRAY);
|
expect(JsonToken.BEGIN_ARRAY);
|
||||||
JsonArray array = (JsonArray) peekStack();
|
JsonArray array = (JsonArray) peekStack();
|
||||||
stack.add(array.iterator());
|
stack.add(array.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void endArray() throws IOException {
|
@Override public void endArray() throws IOException {
|
||||||
expect(JsonToken.END_ARRAY);
|
expect(JsonToken.END_ARRAY);
|
||||||
popStack(); // empty iterator
|
popStack(); // empty iterator
|
||||||
popStack(); // array
|
popStack(); // array
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void beginObject() throws IOException {
|
@Override public void beginObject() throws IOException {
|
||||||
expect(JsonToken.BEGIN_OBJECT);
|
expect(JsonToken.BEGIN_OBJECT);
|
||||||
JsonObject object = (JsonObject) peekStack();
|
JsonObject object = (JsonObject) peekStack();
|
||||||
stack.add(object.entrySet().iterator());
|
stack.add(object.entrySet().iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void endObject() throws IOException {
|
@Override public void endObject() throws IOException {
|
||||||
expect(JsonToken.END_OBJECT);
|
expect(JsonToken.END_OBJECT);
|
||||||
popStack(); // empty iterator
|
popStack(); // empty iterator
|
||||||
popStack(); // object
|
popStack(); // object
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean hasNext() throws IOException {
|
@Override public boolean hasNext() throws IOException {
|
||||||
JsonToken token = peek();
|
JsonToken token = peek();
|
||||||
return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY;
|
return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonToken peek() throws IOException {
|
@Override public JsonToken peek() throws IOException {
|
||||||
if (stack.isEmpty()) {
|
if (stack.isEmpty()) {
|
||||||
return JsonToken.END_DOCUMENT;
|
return JsonToken.END_DOCUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object o = peekStack();
|
Object o = peekStack();
|
||||||
if (o instanceof Iterator) {
|
if (o instanceof Iterator) {
|
||||||
boolean isObject = stack.get(stack.size() - 2) instanceof JsonObject;
|
boolean isObject = stack.get(stack.size() - 2) instanceof JsonObject;
|
||||||
Iterator<?> iterator = (Iterator<?>) o;
|
Iterator<?> iterator = (Iterator<?>) o;
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
if (isObject) {
|
if (isObject) {
|
||||||
return JsonToken.NAME;
|
return JsonToken.NAME;
|
||||||
} else {
|
} else {
|
||||||
stack.add(iterator.next());
|
stack.add(iterator.next());
|
||||||
return peek();
|
return peek();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return isObject ? JsonToken.END_OBJECT : JsonToken.END_ARRAY;
|
return isObject ? JsonToken.END_OBJECT : JsonToken.END_ARRAY;
|
||||||
}
|
}
|
||||||
} else if (o instanceof JsonObject) {
|
} else if (o instanceof JsonObject) {
|
||||||
return JsonToken.BEGIN_OBJECT;
|
return JsonToken.BEGIN_OBJECT;
|
||||||
} else if (o instanceof JsonArray) {
|
} else if (o instanceof JsonArray) {
|
||||||
return JsonToken.BEGIN_ARRAY;
|
return JsonToken.BEGIN_ARRAY;
|
||||||
} else if (o instanceof JsonPrimitive) {
|
} else if (o instanceof JsonPrimitive) {
|
||||||
JsonPrimitive primitive = (JsonPrimitive) o;
|
JsonPrimitive primitive = (JsonPrimitive) o;
|
||||||
if (primitive.isString()) {
|
if (primitive.isString()) {
|
||||||
return JsonToken.STRING;
|
return JsonToken.STRING;
|
||||||
} else if (primitive.isBoolean()) {
|
} else if (primitive.isBoolean()) {
|
||||||
return JsonToken.BOOLEAN;
|
return JsonToken.BOOLEAN;
|
||||||
} else if (primitive.isNumber()) {
|
} else if (primitive.isNumber()) {
|
||||||
return JsonToken.NUMBER;
|
return JsonToken.NUMBER;
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
} else if (o instanceof JsonNull) {
|
} else if (o instanceof JsonNull) {
|
||||||
return JsonToken.NULL;
|
return JsonToken.NULL;
|
||||||
} else if (o == SENTINEL_CLOSED) {
|
} else if (o == SENTINEL_CLOSED) {
|
||||||
throw new IllegalStateException("JsonReader is closed");
|
throw new IllegalStateException("JsonReader is closed");
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object peekStack() {
|
private Object peekStack() {
|
||||||
return stack.get(stack.size() - 1);
|
return stack.get(stack.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object popStack() {
|
private Object popStack() {
|
||||||
return stack.remove(stack.size() - 1);
|
return stack.remove(stack.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expect(JsonToken expected) throws IOException {
|
private void expect(JsonToken expected) throws IOException {
|
||||||
if (peek() != expected) {
|
if (peek() != expected) {
|
||||||
throw new IllegalStateException("Expected " + expected + " but was " + peek());
|
throw new IllegalStateException("Expected " + expected + " but was " + peek());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String nextName() throws IOException {
|
@Override public String nextName() throws IOException {
|
||||||
expect(JsonToken.NAME);
|
expect(JsonToken.NAME);
|
||||||
Iterator<?> i = (Iterator<?>) peekStack();
|
Iterator<?> i = (Iterator<?>) peekStack();
|
||||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
|
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
|
||||||
stack.add(entry.getValue());
|
stack.add(entry.getValue());
|
||||||
return (String) entry.getKey();
|
return (String) entry.getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String nextString() throws IOException {
|
@Override public String nextString() throws IOException {
|
||||||
JsonToken token = peek();
|
JsonToken token = peek();
|
||||||
if (token != JsonToken.STRING && token != JsonToken.NUMBER) {
|
if (token != JsonToken.STRING && token != JsonToken.NUMBER) {
|
||||||
throw new IllegalStateException("Expected " + JsonToken.STRING + " but was " + token);
|
throw new IllegalStateException("Expected " + JsonToken.STRING + " but was " + token);
|
||||||
}
|
}
|
||||||
return ((JsonPrimitive) popStack()).getAsString();
|
return ((JsonPrimitive) popStack()).getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean nextBoolean() throws IOException {
|
@Override public boolean nextBoolean() throws IOException {
|
||||||
expect(JsonToken.BOOLEAN);
|
expect(JsonToken.BOOLEAN);
|
||||||
return ((JsonPrimitive) popStack()).getAsBoolean();
|
return ((JsonPrimitive) popStack()).getAsBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void nextNull() throws IOException {
|
@Override public void nextNull() throws IOException {
|
||||||
expect(JsonToken.NULL);
|
expect(JsonToken.NULL);
|
||||||
popStack();
|
popStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public double nextDouble() throws IOException {
|
@Override public double nextDouble() throws IOException {
|
||||||
JsonToken token = peek();
|
JsonToken token = peek();
|
||||||
if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
|
if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
|
||||||
throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
|
throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
|
||||||
}
|
}
|
||||||
double result = ((JsonPrimitive) peekStack()).getAsDouble();
|
double result = ((JsonPrimitive) peekStack()).getAsDouble();
|
||||||
if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) {
|
if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) {
|
||||||
throw new NumberFormatException("JSON forbids NaN and infinities: " + result);
|
throw new NumberFormatException("JSON forbids NaN and infinities: " + result);
|
||||||
}
|
}
|
||||||
popStack();
|
popStack();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public long nextLong() throws IOException {
|
@Override public long nextLong() throws IOException {
|
||||||
JsonToken token = peek();
|
JsonToken token = peek();
|
||||||
if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
|
if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
|
||||||
throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
|
throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
|
||||||
}
|
}
|
||||||
long result = ((JsonPrimitive) peekStack()).getAsLong();
|
long result = ((JsonPrimitive) peekStack()).getAsLong();
|
||||||
popStack();
|
popStack();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int nextInt() throws IOException {
|
@Override public int nextInt() throws IOException {
|
||||||
JsonToken token = peek();
|
JsonToken token = peek();
|
||||||
if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
|
if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
|
||||||
throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
|
throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token);
|
||||||
}
|
}
|
||||||
int result = ((JsonPrimitive) peekStack()).getAsInt();
|
int result = ((JsonPrimitive) peekStack()).getAsInt();
|
||||||
popStack();
|
popStack();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void close() throws IOException {
|
@Override public void close() throws IOException {
|
||||||
stack.clear();
|
stack.clear();
|
||||||
stack.add(SENTINEL_CLOSED);
|
stack.add(SENTINEL_CLOSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void skipValue() throws IOException {
|
@Override public void skipValue() throws IOException {
|
||||||
if (peek() == JsonToken.NAME) {
|
if (peek() == JsonToken.NAME) {
|
||||||
nextName();
|
nextName();
|
||||||
} else {
|
} else {
|
||||||
popStack();
|
popStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
return getClass().getSimpleName();
|
return getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void promoteNameToValue() throws IOException {
|
public void promoteNameToValue() throws IOException {
|
||||||
expect(JsonToken.NAME);
|
expect(JsonToken.NAME);
|
||||||
Iterator<?> i = (Iterator<?>) peekStack();
|
Iterator<?> i = (Iterator<?>) peekStack();
|
||||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
|
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
|
||||||
stack.add(entry.getValue());
|
stack.add(entry.getValue());
|
||||||
stack.add(new JsonPrimitive((String)entry.getKey()));
|
stack.add(new JsonPrimitive((String)entry.getKey()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,200 +1,200 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonNull;
|
import com.google.gson.JsonNull;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This writer creates a JsonElement.
|
* This writer creates a JsonElement.
|
||||||
*/
|
*/
|
||||||
public final class JsonTreeWriter extends JsonWriter {
|
public final class JsonTreeWriter extends JsonWriter {
|
||||||
private static final Writer UNWRITABLE_WRITER = new Writer() {
|
private static final Writer UNWRITABLE_WRITER = new Writer() {
|
||||||
@Override public void write(char[] buffer, int offset, int counter) {
|
@Override public void write(char[] buffer, int offset, int counter) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@Override public void flush() throws IOException {
|
@Override public void flush() throws IOException {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@Override public void close() throws IOException {
|
@Override public void close() throws IOException {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/** Added to the top of the stack when this writer is closed to cause following ops to fail. */
|
/** Added to the top of the stack when this writer is closed to cause following ops to fail. */
|
||||||
private static final JsonPrimitive SENTINEL_CLOSED = new JsonPrimitive("closed");
|
private static final JsonPrimitive SENTINEL_CLOSED = new JsonPrimitive("closed");
|
||||||
|
|
||||||
/** The JsonElements and JsonArrays under modification, outermost to innermost. */
|
/** The JsonElements and JsonArrays under modification, outermost to innermost. */
|
||||||
private final List<JsonElement> stack = new ArrayList<JsonElement>();
|
private final List<JsonElement> stack = new ArrayList<JsonElement>();
|
||||||
|
|
||||||
/** The name for the next JSON object value. If non-null, the top of the stack is a JsonObject. */
|
/** The name for the next JSON object value. If non-null, the top of the stack is a JsonObject. */
|
||||||
private String pendingName;
|
private String pendingName;
|
||||||
|
|
||||||
/** the JSON element constructed by this writer. */
|
/** the JSON element constructed by this writer. */
|
||||||
private JsonElement product = JsonNull.INSTANCE; // TODO: is this really what we want?;
|
private JsonElement product = JsonNull.INSTANCE; // TODO: is this really what we want?;
|
||||||
|
|
||||||
public JsonTreeWriter() {
|
public JsonTreeWriter() {
|
||||||
super(UNWRITABLE_WRITER);
|
super(UNWRITABLE_WRITER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the top level object produced by this writer.
|
* Returns the top level object produced by this writer.
|
||||||
*/
|
*/
|
||||||
public JsonElement get() {
|
public JsonElement get() {
|
||||||
if (!stack.isEmpty()) {
|
if (!stack.isEmpty()) {
|
||||||
throw new IllegalStateException("Expected one JSON element but was " + stack);
|
throw new IllegalStateException("Expected one JSON element but was " + stack);
|
||||||
}
|
}
|
||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonElement peek() {
|
private JsonElement peek() {
|
||||||
return stack.get(stack.size() - 1);
|
return stack.get(stack.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void put(JsonElement value) {
|
private void put(JsonElement value) {
|
||||||
if (pendingName != null) {
|
if (pendingName != null) {
|
||||||
if (!value.isJsonNull() || getSerializeNulls()) {
|
if (!value.isJsonNull() || getSerializeNulls()) {
|
||||||
JsonObject object = (JsonObject) peek();
|
JsonObject object = (JsonObject) peek();
|
||||||
object.add(pendingName, value);
|
object.add(pendingName, value);
|
||||||
}
|
}
|
||||||
pendingName = null;
|
pendingName = null;
|
||||||
} else if (stack.isEmpty()) {
|
} else if (stack.isEmpty()) {
|
||||||
product = value;
|
product = value;
|
||||||
} else {
|
} else {
|
||||||
JsonElement element = peek();
|
JsonElement element = peek();
|
||||||
if (element instanceof JsonArray) {
|
if (element instanceof JsonArray) {
|
||||||
((JsonArray) element).add(value);
|
((JsonArray) element).add(value);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter beginArray() throws IOException {
|
@Override public JsonWriter beginArray() throws IOException {
|
||||||
JsonArray array = new JsonArray();
|
JsonArray array = new JsonArray();
|
||||||
put(array);
|
put(array);
|
||||||
stack.add(array);
|
stack.add(array);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter endArray() throws IOException {
|
@Override public JsonWriter endArray() throws IOException {
|
||||||
if (stack.isEmpty() || pendingName != null) {
|
if (stack.isEmpty() || pendingName != null) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
JsonElement element = peek();
|
JsonElement element = peek();
|
||||||
if (element instanceof JsonArray) {
|
if (element instanceof JsonArray) {
|
||||||
stack.remove(stack.size() - 1);
|
stack.remove(stack.size() - 1);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter beginObject() throws IOException {
|
@Override public JsonWriter beginObject() throws IOException {
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
put(object);
|
put(object);
|
||||||
stack.add(object);
|
stack.add(object);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter endObject() throws IOException {
|
@Override public JsonWriter endObject() throws IOException {
|
||||||
if (stack.isEmpty() || pendingName != null) {
|
if (stack.isEmpty() || pendingName != null) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
JsonElement element = peek();
|
JsonElement element = peek();
|
||||||
if (element instanceof JsonObject) {
|
if (element instanceof JsonObject) {
|
||||||
stack.remove(stack.size() - 1);
|
stack.remove(stack.size() - 1);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter name(String name) throws IOException {
|
@Override public JsonWriter name(String name) throws IOException {
|
||||||
if (stack.isEmpty() || pendingName != null) {
|
if (stack.isEmpty() || pendingName != null) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
JsonElement element = peek();
|
JsonElement element = peek();
|
||||||
if (element instanceof JsonObject) {
|
if (element instanceof JsonObject) {
|
||||||
pendingName = name;
|
pendingName = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(String value) throws IOException {
|
@Override public JsonWriter value(String value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return nullValue();
|
return nullValue();
|
||||||
}
|
}
|
||||||
put(new JsonPrimitive(value));
|
put(new JsonPrimitive(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter nullValue() throws IOException {
|
@Override public JsonWriter nullValue() throws IOException {
|
||||||
put(JsonNull.INSTANCE);
|
put(JsonNull.INSTANCE);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(boolean value) throws IOException {
|
@Override public JsonWriter value(boolean value) throws IOException {
|
||||||
put(new JsonPrimitive(value));
|
put(new JsonPrimitive(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(double value) throws IOException {
|
@Override public JsonWriter value(double value) throws IOException {
|
||||||
if (!isLenient() && (Double.isNaN(value) || Double.isInfinite(value))) {
|
if (!isLenient() && (Double.isNaN(value) || Double.isInfinite(value))) {
|
||||||
throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
|
throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
|
||||||
}
|
}
|
||||||
put(new JsonPrimitive(value));
|
put(new JsonPrimitive(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(long value) throws IOException {
|
@Override public JsonWriter value(long value) throws IOException {
|
||||||
put(new JsonPrimitive(value));
|
put(new JsonPrimitive(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public JsonWriter value(Number value) throws IOException {
|
@Override public JsonWriter value(Number value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return nullValue();
|
return nullValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLenient()) {
|
if (!isLenient()) {
|
||||||
double d = value.doubleValue();
|
double d = value.doubleValue();
|
||||||
if (Double.isNaN(d) || Double.isInfinite(d)) {
|
if (Double.isNaN(d) || Double.isInfinite(d)) {
|
||||||
throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
|
throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
put(new JsonPrimitive(value));
|
put(new JsonPrimitive(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void flush() throws IOException {
|
@Override public void flush() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void close() throws IOException {
|
@Override public void close() throws IOException {
|
||||||
if (!stack.isEmpty()) {
|
if (!stack.isEmpty()) {
|
||||||
throw new IOException("Incomplete document");
|
throw new IOException("Incomplete document");
|
||||||
}
|
}
|
||||||
stack.add(SENTINEL_CLOSED);
|
stack.add(SENTINEL_CLOSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,277 +1,277 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
import com.google.gson.internal.ConstructorConstructor;
|
import com.google.gson.internal.ConstructorConstructor;
|
||||||
import com.google.gson.internal.JsonReaderInternalAccess;
|
import com.google.gson.internal.JsonReaderInternalAccess;
|
||||||
import com.google.gson.internal.ObjectConstructor;
|
import com.google.gson.internal.ObjectConstructor;
|
||||||
import com.google.gson.internal.Streams;
|
import com.google.gson.internal.Streams;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts maps to either JSON objects or JSON arrays.
|
* Adapts maps to either JSON objects or JSON arrays.
|
||||||
*
|
*
|
||||||
* <h3>Maps as JSON objects</h3>
|
* <h3>Maps as JSON objects</h3>
|
||||||
* For primitive keys or when complex map key serialization is not enabled, this
|
* For primitive keys or when complex map key serialization is not enabled, this
|
||||||
* converts Java {@link Map Maps} to JSON Objects. This requires that map keys
|
* converts Java {@link Map Maps} to JSON Objects. This requires that map keys
|
||||||
* can be serialized as strings; this is insufficient for some key types. For
|
* can be serialized as strings; this is insufficient for some key types. For
|
||||||
* example, consider a map whose keys are points on a grid. The default JSON
|
* example, consider a map whose keys are points on a grid. The default JSON
|
||||||
* form encodes reasonably: <pre> {@code
|
* form encodes reasonably: <pre> {@code
|
||||||
* Map<Point, String> original = new LinkedHashMap<Point, String>();
|
* Map<Point, String> original = new LinkedHashMap<Point, String>();
|
||||||
* original.put(new Point(5, 6), "a");
|
* original.put(new Point(5, 6), "a");
|
||||||
* original.put(new Point(8, 8), "b");
|
* original.put(new Point(8, 8), "b");
|
||||||
* System.out.println(gson.toJson(original, type));
|
* System.out.println(gson.toJson(original, type));
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* The above code prints this JSON object:<pre> {@code
|
* The above code prints this JSON object:<pre> {@code
|
||||||
* {
|
* {
|
||||||
* "(5,6)": "a",
|
* "(5,6)": "a",
|
||||||
* "(8,8)": "b"
|
* "(8,8)": "b"
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* But GSON is unable to deserialize this value because the JSON string name is
|
* But GSON is unable to deserialize this value because the JSON string name is
|
||||||
* just the {@link Object#toString() toString()} of the map key. Attempting to
|
* just the {@link Object#toString() toString()} of the map key. Attempting to
|
||||||
* convert the above JSON to an object fails with a parse exception:
|
* convert the above JSON to an object fails with a parse exception:
|
||||||
* <pre>com.google.gson.JsonParseException: Expecting object found: "(5,6)"
|
* <pre>com.google.gson.JsonParseException: Expecting object found: "(5,6)"
|
||||||
* at com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler
|
* at com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler
|
||||||
* at com.google.gson.ObjectNavigator.navigateClassFields
|
* at com.google.gson.ObjectNavigator.navigateClassFields
|
||||||
* ...</pre>
|
* ...</pre>
|
||||||
*
|
*
|
||||||
* <h3>Maps as JSON arrays</h3>
|
* <h3>Maps as JSON arrays</h3>
|
||||||
* An alternative approach taken by this type adapter when it is required and
|
* An alternative approach taken by this type adapter when it is required and
|
||||||
* complex map key serialization is enabled is to encode maps as arrays of map
|
* complex map key serialization is enabled is to encode maps as arrays of map
|
||||||
* entries. Each map entry is a two element array containing a key and a value.
|
* entries. Each map entry is a two element array containing a key and a value.
|
||||||
* This approach is more flexible because any type can be used as the map's key;
|
* This approach is more flexible because any type can be used as the map's key;
|
||||||
* not just strings. But it's also less portable because the receiver of such
|
* not just strings. But it's also less portable because the receiver of such
|
||||||
* JSON must be aware of the map entry convention.
|
* JSON must be aware of the map entry convention.
|
||||||
*
|
*
|
||||||
* <p>Register this adapter when you are creating your GSON instance.
|
* <p>Register this adapter when you are creating your GSON instance.
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* Gson gson = new GsonBuilder()
|
* Gson gson = new GsonBuilder()
|
||||||
* .registerTypeAdapter(Map.class, new MapAsArrayTypeAdapter())
|
* .registerTypeAdapter(Map.class, new MapAsArrayTypeAdapter())
|
||||||
* .create();
|
* .create();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* This will change the structure of the JSON emitted by the code above. Now we
|
* This will change the structure of the JSON emitted by the code above. Now we
|
||||||
* get an array. In this case the arrays elements are map entries:
|
* get an array. In this case the arrays elements are map entries:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* [
|
* [
|
||||||
* [
|
* [
|
||||||
* {
|
* {
|
||||||
* "x": 5,
|
* "x": 5,
|
||||||
* "y": 6
|
* "y": 6
|
||||||
* },
|
* },
|
||||||
* "a",
|
* "a",
|
||||||
* ],
|
* ],
|
||||||
* [
|
* [
|
||||||
* {
|
* {
|
||||||
* "x": 8,
|
* "x": 8,
|
||||||
* "y": 8
|
* "y": 8
|
||||||
* },
|
* },
|
||||||
* "b"
|
* "b"
|
||||||
* ]
|
* ]
|
||||||
* ]
|
* ]
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* This format will serialize and deserialize just fine as long as this adapter
|
* This format will serialize and deserialize just fine as long as this adapter
|
||||||
* is registered.
|
* is registered.
|
||||||
*/
|
*/
|
||||||
public final class MapTypeAdapterFactory implements TypeAdapterFactory {
|
public final class MapTypeAdapterFactory implements TypeAdapterFactory {
|
||||||
private final ConstructorConstructor constructorConstructor;
|
private final ConstructorConstructor constructorConstructor;
|
||||||
private final boolean complexMapKeySerialization;
|
private final boolean complexMapKeySerialization;
|
||||||
|
|
||||||
public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor,
|
public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor,
|
||||||
boolean complexMapKeySerialization) {
|
boolean complexMapKeySerialization) {
|
||||||
this.constructorConstructor = constructorConstructor;
|
this.constructorConstructor = constructorConstructor;
|
||||||
this.complexMapKeySerialization = complexMapKeySerialization;
|
this.complexMapKeySerialization = complexMapKeySerialization;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
Type type = typeToken.getType();
|
Type type = typeToken.getType();
|
||||||
|
|
||||||
Class<? super T> rawType = typeToken.getRawType();
|
Class<? super T> rawType = typeToken.getRawType();
|
||||||
if (!Map.class.isAssignableFrom(rawType)) {
|
if (!Map.class.isAssignableFrom(rawType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> rawTypeOfSrc = $Gson$Types.getRawType(type);
|
Class<?> rawTypeOfSrc = $Gson$Types.getRawType(type);
|
||||||
Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawTypeOfSrc);
|
Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawTypeOfSrc);
|
||||||
TypeAdapter<?> keyAdapter = getKeyAdapter(gson, keyAndValueTypes[0]);
|
TypeAdapter<?> keyAdapter = getKeyAdapter(gson, keyAndValueTypes[0]);
|
||||||
TypeAdapter<?> valueAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1]));
|
TypeAdapter<?> valueAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1]));
|
||||||
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(typeToken);
|
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(typeToken);
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
// we don't define a type parameter for the key or value types
|
// we don't define a type parameter for the key or value types
|
||||||
TypeAdapter<T> result = new Adapter(gson, keyAndValueTypes[0], keyAdapter,
|
TypeAdapter<T> result = new Adapter(gson, keyAndValueTypes[0], keyAdapter,
|
||||||
keyAndValueTypes[1], valueAdapter, constructor);
|
keyAndValueTypes[1], valueAdapter, constructor);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a type adapter that writes the value as a string.
|
* Returns a type adapter that writes the value as a string.
|
||||||
*/
|
*/
|
||||||
private TypeAdapter<?> getKeyAdapter(Gson context, Type keyType) {
|
private TypeAdapter<?> getKeyAdapter(Gson context, Type keyType) {
|
||||||
return (keyType == boolean.class || keyType == Boolean.class)
|
return (keyType == boolean.class || keyType == Boolean.class)
|
||||||
? TypeAdapters.BOOLEAN_AS_STRING
|
? TypeAdapters.BOOLEAN_AS_STRING
|
||||||
: context.getAdapter(TypeToken.get(keyType));
|
: context.getAdapter(TypeToken.get(keyType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class Adapter<K, V> extends TypeAdapter<Map<K, V>> {
|
private final class Adapter<K, V> extends TypeAdapter<Map<K, V>> {
|
||||||
private final TypeAdapter<K> keyTypeAdapter;
|
private final TypeAdapter<K> keyTypeAdapter;
|
||||||
private final TypeAdapter<V> valueTypeAdapter;
|
private final TypeAdapter<V> valueTypeAdapter;
|
||||||
private final ObjectConstructor<? extends Map<K, V>> constructor;
|
private final ObjectConstructor<? extends Map<K, V>> constructor;
|
||||||
|
|
||||||
public Adapter(Gson context, Type keyType, TypeAdapter<K> keyTypeAdapter,
|
public Adapter(Gson context, Type keyType, TypeAdapter<K> keyTypeAdapter,
|
||||||
Type valueType, TypeAdapter<V> valueTypeAdapter,
|
Type valueType, TypeAdapter<V> valueTypeAdapter,
|
||||||
ObjectConstructor<? extends Map<K, V>> constructor) {
|
ObjectConstructor<? extends Map<K, V>> constructor) {
|
||||||
this.keyTypeAdapter =
|
this.keyTypeAdapter =
|
||||||
new TypeAdapterRuntimeTypeWrapper<K>(context, keyTypeAdapter, keyType);
|
new TypeAdapterRuntimeTypeWrapper<K>(context, keyTypeAdapter, keyType);
|
||||||
this.valueTypeAdapter =
|
this.valueTypeAdapter =
|
||||||
new TypeAdapterRuntimeTypeWrapper<V>(context, valueTypeAdapter, valueType);
|
new TypeAdapterRuntimeTypeWrapper<V>(context, valueTypeAdapter, valueType);
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<K, V> read(JsonReader in) throws IOException {
|
public Map<K, V> read(JsonReader in) throws IOException {
|
||||||
JsonToken peek = in.peek();
|
JsonToken peek = in.peek();
|
||||||
if (peek == JsonToken.NULL) {
|
if (peek == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<K, V> map = constructor.construct();
|
Map<K, V> map = constructor.construct();
|
||||||
|
|
||||||
if (peek == JsonToken.BEGIN_ARRAY) {
|
if (peek == JsonToken.BEGIN_ARRAY) {
|
||||||
in.beginArray();
|
in.beginArray();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
in.beginArray(); // entry array
|
in.beginArray(); // entry array
|
||||||
K key = keyTypeAdapter.read(in);
|
K key = keyTypeAdapter.read(in);
|
||||||
V value = valueTypeAdapter.read(in);
|
V value = valueTypeAdapter.read(in);
|
||||||
V replaced = map.put(key, value);
|
V replaced = map.put(key, value);
|
||||||
if (replaced != null) {
|
if (replaced != null) {
|
||||||
throw new JsonSyntaxException("duplicate key: " + key);
|
throw new JsonSyntaxException("duplicate key: " + key);
|
||||||
}
|
}
|
||||||
in.endArray();
|
in.endArray();
|
||||||
}
|
}
|
||||||
in.endArray();
|
in.endArray();
|
||||||
} else {
|
} else {
|
||||||
in.beginObject();
|
in.beginObject();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
|
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
|
||||||
K key = keyTypeAdapter.read(in);
|
K key = keyTypeAdapter.read(in);
|
||||||
V value = valueTypeAdapter.read(in);
|
V value = valueTypeAdapter.read(in);
|
||||||
V replaced = map.put(key, value);
|
V replaced = map.put(key, value);
|
||||||
if (replaced != null) {
|
if (replaced != null) {
|
||||||
throw new JsonSyntaxException("duplicate key: " + key);
|
throw new JsonSyntaxException("duplicate key: " + key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.endObject();
|
in.endObject();
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(JsonWriter out, Map<K, V> map) throws IOException {
|
public void write(JsonWriter out, Map<K, V> map) throws IOException {
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!complexMapKeySerialization) {
|
if (!complexMapKeySerialization) {
|
||||||
out.beginObject();
|
out.beginObject();
|
||||||
for (Map.Entry<K, V> entry : map.entrySet()) {
|
for (Map.Entry<K, V> entry : map.entrySet()) {
|
||||||
out.name(String.valueOf(entry.getKey()));
|
out.name(String.valueOf(entry.getKey()));
|
||||||
valueTypeAdapter.write(out, entry.getValue());
|
valueTypeAdapter.write(out, entry.getValue());
|
||||||
}
|
}
|
||||||
out.endObject();
|
out.endObject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasComplexKeys = false;
|
boolean hasComplexKeys = false;
|
||||||
List<JsonElement> keys = new ArrayList<JsonElement>(map.size());
|
List<JsonElement> keys = new ArrayList<JsonElement>(map.size());
|
||||||
|
|
||||||
List<V> values = new ArrayList<V>(map.size());
|
List<V> values = new ArrayList<V>(map.size());
|
||||||
for (Map.Entry<K, V> entry : map.entrySet()) {
|
for (Map.Entry<K, V> entry : map.entrySet()) {
|
||||||
JsonElement keyElement = toJsonTree(keyTypeAdapter, entry.getKey());
|
JsonElement keyElement = toJsonTree(keyTypeAdapter, entry.getKey());
|
||||||
keys.add(keyElement);
|
keys.add(keyElement);
|
||||||
values.add(entry.getValue());
|
values.add(entry.getValue());
|
||||||
hasComplexKeys |= keyElement.isJsonArray() || keyElement.isJsonObject();
|
hasComplexKeys |= keyElement.isJsonArray() || keyElement.isJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasComplexKeys) {
|
if (hasComplexKeys) {
|
||||||
out.beginArray();
|
out.beginArray();
|
||||||
for (int i = 0; i < keys.size(); i++) {
|
for (int i = 0; i < keys.size(); i++) {
|
||||||
out.beginArray(); // entry array
|
out.beginArray(); // entry array
|
||||||
Streams.write(keys.get(i), out);
|
Streams.write(keys.get(i), out);
|
||||||
valueTypeAdapter.write(out, values.get(i));
|
valueTypeAdapter.write(out, values.get(i));
|
||||||
out.endArray();
|
out.endArray();
|
||||||
}
|
}
|
||||||
out.endArray();
|
out.endArray();
|
||||||
} else {
|
} else {
|
||||||
out.beginObject();
|
out.beginObject();
|
||||||
for (int i = 0; i < keys.size(); i++) {
|
for (int i = 0; i < keys.size(); i++) {
|
||||||
JsonElement keyElement = keys.get(i);
|
JsonElement keyElement = keys.get(i);
|
||||||
out.name(keyToString(keyElement));
|
out.name(keyToString(keyElement));
|
||||||
valueTypeAdapter.write(out, values.get(i));
|
valueTypeAdapter.write(out, values.get(i));
|
||||||
}
|
}
|
||||||
out.endObject();
|
out.endObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String keyToString(JsonElement keyElement) {
|
private String keyToString(JsonElement keyElement) {
|
||||||
if (keyElement.isJsonPrimitive()) {
|
if (keyElement.isJsonPrimitive()) {
|
||||||
JsonPrimitive primitive = keyElement.getAsJsonPrimitive();
|
JsonPrimitive primitive = keyElement.getAsJsonPrimitive();
|
||||||
if (primitive.isNumber()) {
|
if (primitive.isNumber()) {
|
||||||
return String.valueOf(primitive.getAsNumber());
|
return String.valueOf(primitive.getAsNumber());
|
||||||
} else if (primitive.isBoolean()) {
|
} else if (primitive.isBoolean()) {
|
||||||
return Boolean.toString(primitive.getAsBoolean());
|
return Boolean.toString(primitive.getAsBoolean());
|
||||||
} else if (primitive.isString()) {
|
} else if (primitive.isString()) {
|
||||||
return primitive.getAsString();
|
return primitive.getAsString();
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
} else if (keyElement.isJsonNull()) {
|
} else if (keyElement.isJsonNull()) {
|
||||||
return "null";
|
return "null";
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this when TypeAdapter.toJsonTree() is public
|
// TODO: remove this when TypeAdapter.toJsonTree() is public
|
||||||
private static <T> JsonElement toJsonTree(TypeAdapter<T> typeAdapter, T value) {
|
private static <T> JsonElement toJsonTree(TypeAdapter<T> typeAdapter, T value) {
|
||||||
try {
|
try {
|
||||||
JsonTreeWriter jsonWriter = new JsonTreeWriter();
|
JsonTreeWriter jsonWriter = new JsonTreeWriter();
|
||||||
jsonWriter.setLenient(true);
|
jsonWriter.setLenient(true);
|
||||||
typeAdapter.write(jsonWriter, value);
|
typeAdapter.write(jsonWriter, value);
|
||||||
return jsonWriter.get();
|
return jsonWriter.get();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JsonIOException(e);
|
throw new JsonIOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,107 +1,107 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts types whose static type is only 'Object'. Uses getClass() on
|
* Adapts types whose static type is only 'Object'. Uses getClass() on
|
||||||
* serialization and a primitive/Map/List on deserialization.
|
* serialization and a primitive/Map/List on deserialization.
|
||||||
*/
|
*/
|
||||||
public final class ObjectTypeAdapter extends TypeAdapter<Object> {
|
public final class ObjectTypeAdapter extends TypeAdapter<Object> {
|
||||||
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||||
if (type.getRawType() == Object.class) {
|
if (type.getRawType() == Object.class) {
|
||||||
return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
|
return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
|
|
||||||
private ObjectTypeAdapter(Gson gson) {
|
private ObjectTypeAdapter(Gson gson) {
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Object read(JsonReader in) throws IOException {
|
@Override public Object read(JsonReader in) throws IOException {
|
||||||
JsonToken token = in.peek();
|
JsonToken token = in.peek();
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case BEGIN_ARRAY:
|
case BEGIN_ARRAY:
|
||||||
List<Object> list = new ArrayList<Object>();
|
List<Object> list = new ArrayList<Object>();
|
||||||
in.beginArray();
|
in.beginArray();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
list.add(read(in));
|
list.add(read(in));
|
||||||
}
|
}
|
||||||
in.endArray();
|
in.endArray();
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
case BEGIN_OBJECT:
|
case BEGIN_OBJECT:
|
||||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||||
in.beginObject();
|
in.beginObject();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
map.put(in.nextName(), read(in));
|
map.put(in.nextName(), read(in));
|
||||||
}
|
}
|
||||||
in.endObject();
|
in.endObject();
|
||||||
return map;
|
return map;
|
||||||
|
|
||||||
case STRING:
|
case STRING:
|
||||||
return in.nextString();
|
return in.nextString();
|
||||||
|
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
return in.nextDouble();
|
return in.nextDouble();
|
||||||
|
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
return in.nextBoolean();
|
return in.nextBoolean();
|
||||||
|
|
||||||
case NULL:
|
case NULL:
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override public void write(JsonWriter out, Object value) throws IOException {
|
@Override public void write(JsonWriter out, Object value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
|
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
|
||||||
if (typeAdapter instanceof ObjectTypeAdapter) {
|
if (typeAdapter instanceof ObjectTypeAdapter) {
|
||||||
out.beginObject();
|
out.beginObject();
|
||||||
out.endObject();
|
out.endObject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typeAdapter.write(out, value);
|
typeAdapter.write(out, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,209 +1,209 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.FieldNamingStrategy;
|
import com.google.gson.FieldNamingStrategy;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
import com.google.gson.internal.ConstructorConstructor;
|
import com.google.gson.internal.ConstructorConstructor;
|
||||||
import com.google.gson.internal.Excluder;
|
import com.google.gson.internal.Excluder;
|
||||||
import com.google.gson.internal.ObjectConstructor;
|
import com.google.gson.internal.ObjectConstructor;
|
||||||
import com.google.gson.internal.Primitives;
|
import com.google.gson.internal.Primitives;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type adapter that reflects over the fields and methods of a class.
|
* Type adapter that reflects over the fields and methods of a class.
|
||||||
*/
|
*/
|
||||||
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
|
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
|
||||||
private final ConstructorConstructor constructorConstructor;
|
private final ConstructorConstructor constructorConstructor;
|
||||||
private final FieldNamingStrategy fieldNamingPolicy;
|
private final FieldNamingStrategy fieldNamingPolicy;
|
||||||
private final Excluder excluder;
|
private final Excluder excluder;
|
||||||
|
|
||||||
public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor,
|
public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor,
|
||||||
FieldNamingStrategy fieldNamingPolicy, Excluder excluder) {
|
FieldNamingStrategy fieldNamingPolicy, Excluder excluder) {
|
||||||
this.constructorConstructor = constructorConstructor;
|
this.constructorConstructor = constructorConstructor;
|
||||||
this.fieldNamingPolicy = fieldNamingPolicy;
|
this.fieldNamingPolicy = fieldNamingPolicy;
|
||||||
this.excluder = excluder;
|
this.excluder = excluder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean excludeField(Field f, boolean serialize) {
|
public boolean excludeField(Field f, boolean serialize) {
|
||||||
return !excluder.excludeClass(f.getType(), serialize) && !excluder.excludeField(f, serialize);
|
return !excluder.excludeClass(f.getType(), serialize) && !excluder.excludeField(f, serialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldName(Field f) {
|
private String getFieldName(Field f) {
|
||||||
SerializedName serializedName = f.getAnnotation(SerializedName.class);
|
SerializedName serializedName = f.getAnnotation(SerializedName.class);
|
||||||
return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value();
|
return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
|
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
|
||||||
Class<? super T> raw = type.getRawType();
|
Class<? super T> raw = type.getRawType();
|
||||||
|
|
||||||
if (!Object.class.isAssignableFrom(raw)) {
|
if (!Object.class.isAssignableFrom(raw)) {
|
||||||
return null; // it's a primitive!
|
return null; // it's a primitive!
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(type);
|
ObjectConstructor<T> constructor = constructorConstructor.getConstructor(type);
|
||||||
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
|
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
|
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
|
||||||
final Gson context, final Field field, final String name,
|
final Gson context, final Field field, final String name,
|
||||||
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
|
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
|
||||||
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
|
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
|
||||||
|
|
||||||
// special casing primitives here saves ~5% on Android...
|
// special casing primitives here saves ~5% on Android...
|
||||||
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
|
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
|
||||||
final TypeAdapter<?> typeAdapter = context.getAdapter(fieldType);
|
final TypeAdapter<?> typeAdapter = context.getAdapter(fieldType);
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
|
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
|
||||||
@Override void write(JsonWriter writer, Object value)
|
@Override void write(JsonWriter writer, Object value)
|
||||||
throws IOException, IllegalAccessException {
|
throws IOException, IllegalAccessException {
|
||||||
Object fieldValue = field.get(value);
|
Object fieldValue = field.get(value);
|
||||||
TypeAdapter t =
|
TypeAdapter t =
|
||||||
new TypeAdapterRuntimeTypeWrapper(context, this.typeAdapter, fieldType.getType());
|
new TypeAdapterRuntimeTypeWrapper(context, this.typeAdapter, fieldType.getType());
|
||||||
t.write(writer, fieldValue);
|
t.write(writer, fieldValue);
|
||||||
}
|
}
|
||||||
@Override void read(JsonReader reader, Object value)
|
@Override void read(JsonReader reader, Object value)
|
||||||
throws IOException, IllegalAccessException {
|
throws IOException, IllegalAccessException {
|
||||||
Object fieldValue = typeAdapter.read(reader);
|
Object fieldValue = typeAdapter.read(reader);
|
||||||
if (fieldValue != null || !isPrimitive) {
|
if (fieldValue != null || !isPrimitive) {
|
||||||
field.set(value, fieldValue);
|
field.set(value, fieldValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
|
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
|
||||||
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
|
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
|
||||||
if (raw.isInterface()) {
|
if (raw.isInterface()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type declaredType = type.getType();
|
Type declaredType = type.getType();
|
||||||
while (raw != Object.class) {
|
while (raw != Object.class) {
|
||||||
Field[] fields = raw.getDeclaredFields();
|
Field[] fields = raw.getDeclaredFields();
|
||||||
for (Field field : fields) {
|
for (Field field : fields) {
|
||||||
boolean serialize = excludeField(field, true);
|
boolean serialize = excludeField(field, true);
|
||||||
boolean deserialize = excludeField(field, false);
|
boolean deserialize = excludeField(field, false);
|
||||||
if (!serialize && !deserialize) {
|
if (!serialize && !deserialize) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
|
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
|
||||||
BoundField boundField = createBoundField(context, field, getFieldName(field),
|
BoundField boundField = createBoundField(context, field, getFieldName(field),
|
||||||
TypeToken.get(fieldType), serialize, deserialize);
|
TypeToken.get(fieldType), serialize, deserialize);
|
||||||
BoundField previous = result.put(boundField.name, boundField);
|
BoundField previous = result.put(boundField.name, boundField);
|
||||||
if (previous != null) {
|
if (previous != null) {
|
||||||
throw new IllegalArgumentException(declaredType
|
throw new IllegalArgumentException(declaredType
|
||||||
+ " declares multiple JSON fields named " + previous.name);
|
+ " declares multiple JSON fields named " + previous.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
|
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
|
||||||
raw = type.getRawType();
|
raw = type.getRawType();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static abstract class BoundField {
|
static abstract class BoundField {
|
||||||
final String name;
|
final String name;
|
||||||
final boolean serialized;
|
final boolean serialized;
|
||||||
final boolean deserialized;
|
final boolean deserialized;
|
||||||
|
|
||||||
protected BoundField(String name, boolean serialized, boolean deserialized) {
|
protected BoundField(String name, boolean serialized, boolean deserialized) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.serialized = serialized;
|
this.serialized = serialized;
|
||||||
this.deserialized = deserialized;
|
this.deserialized = deserialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
|
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
|
||||||
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
|
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class Adapter<T> extends TypeAdapter<T> {
|
public final class Adapter<T> extends TypeAdapter<T> {
|
||||||
private final ObjectConstructor<T> constructor;
|
private final ObjectConstructor<T> constructor;
|
||||||
private final Map<String, BoundField> boundFields;
|
private final Map<String, BoundField> boundFields;
|
||||||
|
|
||||||
private Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
|
private Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
this.boundFields = boundFields;
|
this.boundFields = boundFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T read(JsonReader in) throws IOException {
|
public T read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
T instance = constructor.construct();
|
T instance = constructor.construct();
|
||||||
|
|
||||||
// TODO: null out the other fields?
|
// TODO: null out the other fields?
|
||||||
|
|
||||||
try {
|
try {
|
||||||
in.beginObject();
|
in.beginObject();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
String name = in.nextName();
|
String name = in.nextName();
|
||||||
BoundField field = boundFields.get(name);
|
BoundField field = boundFields.get(name);
|
||||||
if (field == null || !field.deserialized) {
|
if (field == null || !field.deserialized) {
|
||||||
// TODO: define a better policy
|
// TODO: define a better policy
|
||||||
in.skipValue();
|
in.skipValue();
|
||||||
} else {
|
} else {
|
||||||
field.read(in, instance);
|
field.read(in, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
in.endObject();
|
in.endObject();
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, T value) throws IOException {
|
public void write(JsonWriter out, T value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue(); // TODO: better policy here?
|
out.nullValue(); // TODO: better policy here?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.beginObject();
|
out.beginObject();
|
||||||
try {
|
try {
|
||||||
for (BoundField boundField : boundFields.values()) {
|
for (BoundField boundField : boundFields.values()) {
|
||||||
if (boundField.serialized) {
|
if (boundField.serialized) {
|
||||||
out.name(boundField.name);
|
out.name(boundField.name);
|
||||||
boundField.write(out, value);
|
boundField.write(out, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
out.endObject();
|
out.endObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +1,67 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for java.sql.Date. Although this class appears stateless, it is not.
|
* Adapter for java.sql.Date. Although this class appears stateless, it is not.
|
||||||
* DateFormat captures its time zone and locale when it is created, which gives
|
* DateFormat captures its time zone and locale when it is created, which gives
|
||||||
* this class state. DateFormat isn't thread safe either, so this class has
|
* this class state. DateFormat isn't thread safe either, so this class has
|
||||||
* to synchronize its read and write methods.
|
* to synchronize its read and write methods.
|
||||||
*/
|
*/
|
||||||
public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
|
public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
|
||||||
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
||||||
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
return typeToken.getRawType() == java.sql.Date.class
|
return typeToken.getRawType() == java.sql.Date.class
|
||||||
? (TypeAdapter<T>) new SqlDateTypeAdapter() : null;
|
? (TypeAdapter<T>) new SqlDateTypeAdapter() : null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
|
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized java.sql.Date read(JsonReader in) throws IOException {
|
public synchronized java.sql.Date read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final long utilDate = format.parse(in.nextString()).getTime();
|
final long utilDate = format.parse(in.nextString()).getTime();
|
||||||
return new java.sql.Date(utilDate);
|
return new java.sql.Date(utilDate);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException {
|
public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException {
|
||||||
out.value(value == null ? null : format.format(value));
|
out.value(value == null ? null : format.format(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,66 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.internal.bind;
|
package com.google.gson.internal.bind;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.TypeAdapter;
|
import com.google.gson.TypeAdapter;
|
||||||
import com.google.gson.TypeAdapterFactory;
|
import com.google.gson.TypeAdapterFactory;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.stream.JsonToken;
|
import com.google.gson.stream.JsonToken;
|
||||||
import com.google.gson.stream.JsonWriter;
|
import com.google.gson.stream.JsonWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for Time. Although this class appears stateless, it is not.
|
* Adapter for Time. Although this class appears stateless, it is not.
|
||||||
* DateFormat captures its time zone and locale when it is created, which gives
|
* DateFormat captures its time zone and locale when it is created, which gives
|
||||||
* this class state. DateFormat isn't thread safe either, so this class has
|
* this class state. DateFormat isn't thread safe either, so this class has
|
||||||
* to synchronize its read and write methods.
|
* to synchronize its read and write methods.
|
||||||
*/
|
*/
|
||||||
public final class TimeTypeAdapter extends TypeAdapter<Time> {
|
public final class TimeTypeAdapter extends TypeAdapter<Time> {
|
||||||
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
||||||
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
||||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||||
return typeToken.getRawType() == Time.class ? (TypeAdapter<T>) new TimeTypeAdapter() : null;
|
return typeToken.getRawType() == Time.class ? (TypeAdapter<T>) new TimeTypeAdapter() : null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final DateFormat format = new SimpleDateFormat("hh:mm:ss a");
|
private final DateFormat format = new SimpleDateFormat("hh:mm:ss a");
|
||||||
|
|
||||||
@Override public synchronized Time read(JsonReader in) throws IOException {
|
@Override public synchronized Time read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Date date = format.parse(in.nextString());
|
Date date = format.parse(in.nextString());
|
||||||
return new Time(date.getTime());
|
return new Time(date.getTime());
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public synchronized void write(JsonWriter out, Time value) throws IOException {
|
@Override public synchronized void write(JsonWriter out, Time value) throws IOException {
|
||||||
out.value(value == null ? null : format.format(value));
|
out.value(value == null ? null : format.format(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Do NOT use any class in this package as they are meant for internal use in Gson.
|
* Do NOT use any class in this package as they are meant for internal use in Gson.
|
||||||
* These classes will very likely change incompatibly in future versions. You have been warned.
|
* These classes will very likely change incompatibly in future versions. You have been warned.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh, Joel Leitch, Jesse Wilson
|
* @author Inderjeet Singh, Joel Leitch, Jesse Wilson
|
||||||
*/
|
*/
|
||||||
package com.google.gson.internal;
|
package com.google.gson.internal;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* This package provides the {@link com.google.gson.Gson} class to convert Json to Java and
|
* This package provides the {@link com.google.gson.Gson} class to convert Json to Java and
|
||||||
* vice-versa.
|
* vice-versa.
|
||||||
*
|
*
|
||||||
* <p>The primary class to use is {@link com.google.gson.Gson} which can be constructed with
|
* <p>The primary class to use is {@link com.google.gson.Gson} which can be constructed with
|
||||||
* {@code new Gson()} (using default settings) or by using {@link com.google.gson.GsonBuilder}
|
* {@code new Gson()} (using default settings) or by using {@link com.google.gson.GsonBuilder}
|
||||||
* (to configure various options such as using versioning and so on).</p>
|
* (to configure various options such as using versioning and so on).</p>
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh, Joel Leitch
|
* @author Inderjeet Singh, Joel Leitch
|
||||||
*/
|
*/
|
||||||
package com.google.gson;
|
package com.google.gson;
|
||||||
|
|||||||
@@ -1,305 +1,305 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Google Inc.
|
* Copyright (C) 2008 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.reflect;
|
package com.google.gson.reflect;
|
||||||
|
|
||||||
import com.google.gson.internal.$Gson$Types;
|
import com.google.gson.internal.$Gson$Types;
|
||||||
import com.google.gson.internal.$Gson$Preconditions;
|
import com.google.gson.internal.$Gson$Preconditions;
|
||||||
import java.lang.reflect.GenericArrayType;
|
import java.lang.reflect.GenericArrayType;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.TypeVariable;
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a generic type {@code T}. Java doesn't yet provide a way to
|
* Represents a generic type {@code T}. Java doesn't yet provide a way to
|
||||||
* represent generic types, so this class does. Forces clients to create a
|
* represent generic types, so this class does. Forces clients to create a
|
||||||
* subclass of this class which enables retrieval the type information even at
|
* subclass of this class which enables retrieval the type information even at
|
||||||
* runtime.
|
* runtime.
|
||||||
*
|
*
|
||||||
* <p>For example, to create a type literal for {@code List<String>}, you can
|
* <p>For example, to create a type literal for {@code List<String>}, you can
|
||||||
* create an empty anonymous inner class:
|
* create an empty anonymous inner class:
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* {@code TypeToken<List<String>> list = new TypeToken<List<String>>() {};}
|
* {@code TypeToken<List<String>> list = new TypeToken<List<String>>() {};}
|
||||||
*
|
*
|
||||||
* <p>This syntax cannot be used to create type literals that have wildcard
|
* <p>This syntax cannot be used to create type literals that have wildcard
|
||||||
* parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
|
* parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
|
||||||
*
|
*
|
||||||
* @author Bob Lee
|
* @author Bob Lee
|
||||||
* @author Sven Mawson
|
* @author Sven Mawson
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
*/
|
*/
|
||||||
public class TypeToken<T> {
|
public class TypeToken<T> {
|
||||||
final Class<? super T> rawType;
|
final Class<? super T> rawType;
|
||||||
final Type type;
|
final Type type;
|
||||||
final int hashCode;
|
final int hashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new type literal. Derives represented class from type
|
* Constructs a new type literal. Derives represented class from type
|
||||||
* parameter.
|
* parameter.
|
||||||
*
|
*
|
||||||
* <p>Clients create an empty anonymous subclass. Doing so embeds the type
|
* <p>Clients create an empty anonymous subclass. Doing so embeds the type
|
||||||
* parameter in the anonymous class's type hierarchy so we can reconstitute it
|
* parameter in the anonymous class's type hierarchy so we can reconstitute it
|
||||||
* at runtime despite erasure.
|
* at runtime despite erasure.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected TypeToken() {
|
protected TypeToken() {
|
||||||
this.type = getSuperclassTypeParameter(getClass());
|
this.type = getSuperclassTypeParameter(getClass());
|
||||||
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
|
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
|
||||||
this.hashCode = type.hashCode();
|
this.hashCode = type.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsafe. Constructs a type literal manually.
|
* Unsafe. Constructs a type literal manually.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
TypeToken(Type type) {
|
TypeToken(Type type) {
|
||||||
this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
|
this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
|
||||||
this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
|
this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
|
||||||
this.hashCode = this.type.hashCode();
|
this.hashCode = this.type.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type from super class's type parameter in {@link $Gson$Types#canonicalize
|
* Returns the type from super class's type parameter in {@link $Gson$Types#canonicalize
|
||||||
* canonical form}.
|
* canonical form}.
|
||||||
*/
|
*/
|
||||||
static Type getSuperclassTypeParameter(Class<?> subclass) {
|
static Type getSuperclassTypeParameter(Class<?> subclass) {
|
||||||
Type superclass = subclass.getGenericSuperclass();
|
Type superclass = subclass.getGenericSuperclass();
|
||||||
if (superclass instanceof Class) {
|
if (superclass instanceof Class) {
|
||||||
throw new RuntimeException("Missing type parameter.");
|
throw new RuntimeException("Missing type parameter.");
|
||||||
}
|
}
|
||||||
ParameterizedType parameterized = (ParameterizedType) superclass;
|
ParameterizedType parameterized = (ParameterizedType) superclass;
|
||||||
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
|
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the raw (non-generic) type for this type.
|
* Returns the raw (non-generic) type for this type.
|
||||||
*/
|
*/
|
||||||
public final Class<? super T> getRawType() {
|
public final Class<? super T> getRawType() {
|
||||||
return rawType;
|
return rawType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets underlying {@code Type} instance.
|
* Gets underlying {@code Type} instance.
|
||||||
*/
|
*/
|
||||||
public final Type getType() {
|
public final Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this type is assignable from the given class object.
|
* Check if this type is assignable from the given class object.
|
||||||
*
|
*
|
||||||
* @deprecated this implementation may be inconsistent with javac for types
|
* @deprecated this implementation may be inconsistent with javac for types
|
||||||
* with wildcards.
|
* with wildcards.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isAssignableFrom(Class<?> cls) {
|
public boolean isAssignableFrom(Class<?> cls) {
|
||||||
return isAssignableFrom((Type) cls);
|
return isAssignableFrom((Type) cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this type is assignable from the given Type.
|
* Check if this type is assignable from the given Type.
|
||||||
*
|
*
|
||||||
* @deprecated this implementation may be inconsistent with javac for types
|
* @deprecated this implementation may be inconsistent with javac for types
|
||||||
* with wildcards.
|
* with wildcards.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isAssignableFrom(Type from) {
|
public boolean isAssignableFrom(Type from) {
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.equals(from)) {
|
if (type.equals(from)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type instanceof Class<?>) {
|
if (type instanceof Class<?>) {
|
||||||
return rawType.isAssignableFrom($Gson$Types.getRawType(from));
|
return rawType.isAssignableFrom($Gson$Types.getRawType(from));
|
||||||
} else if (type instanceof ParameterizedType) {
|
} else if (type instanceof ParameterizedType) {
|
||||||
return isAssignableFrom(from, (ParameterizedType) type,
|
return isAssignableFrom(from, (ParameterizedType) type,
|
||||||
new HashMap<String, Type>());
|
new HashMap<String, Type>());
|
||||||
} else if (type instanceof GenericArrayType) {
|
} else if (type instanceof GenericArrayType) {
|
||||||
return rawType.isAssignableFrom($Gson$Types.getRawType(from))
|
return rawType.isAssignableFrom($Gson$Types.getRawType(from))
|
||||||
&& isAssignableFrom(from, (GenericArrayType) type);
|
&& isAssignableFrom(from, (GenericArrayType) type);
|
||||||
} else {
|
} else {
|
||||||
throw buildUnexpectedTypeError(
|
throw buildUnexpectedTypeError(
|
||||||
type, Class.class, ParameterizedType.class, GenericArrayType.class);
|
type, Class.class, ParameterizedType.class, GenericArrayType.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this type is assignable from the given type token.
|
* Check if this type is assignable from the given type token.
|
||||||
*
|
*
|
||||||
* @deprecated this implementation may be inconsistent with javac for types
|
* @deprecated this implementation may be inconsistent with javac for types
|
||||||
* with wildcards.
|
* with wildcards.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isAssignableFrom(TypeToken<?> token) {
|
public boolean isAssignableFrom(TypeToken<?> token) {
|
||||||
return isAssignableFrom(token.getType());
|
return isAssignableFrom(token.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private helper function that performs some assignability checks for
|
* Private helper function that performs some assignability checks for
|
||||||
* the provided GenericArrayType.
|
* the provided GenericArrayType.
|
||||||
*/
|
*/
|
||||||
private static boolean isAssignableFrom(Type from, GenericArrayType to) {
|
private static boolean isAssignableFrom(Type from, GenericArrayType to) {
|
||||||
Type toGenericComponentType = to.getGenericComponentType();
|
Type toGenericComponentType = to.getGenericComponentType();
|
||||||
if (toGenericComponentType instanceof ParameterizedType) {
|
if (toGenericComponentType instanceof ParameterizedType) {
|
||||||
Type t = from;
|
Type t = from;
|
||||||
if (from instanceof GenericArrayType) {
|
if (from instanceof GenericArrayType) {
|
||||||
t = ((GenericArrayType) from).getGenericComponentType();
|
t = ((GenericArrayType) from).getGenericComponentType();
|
||||||
} else if (from instanceof Class<?>) {
|
} else if (from instanceof Class<?>) {
|
||||||
Class<?> classType = (Class<?>) from;
|
Class<?> classType = (Class<?>) from;
|
||||||
while (classType.isArray()) {
|
while (classType.isArray()) {
|
||||||
classType = classType.getComponentType();
|
classType = classType.getComponentType();
|
||||||
}
|
}
|
||||||
t = classType;
|
t = classType;
|
||||||
}
|
}
|
||||||
return isAssignableFrom(t, (ParameterizedType) toGenericComponentType,
|
return isAssignableFrom(t, (ParameterizedType) toGenericComponentType,
|
||||||
new HashMap<String, Type>());
|
new HashMap<String, Type>());
|
||||||
}
|
}
|
||||||
// No generic defined on "to"; therefore, return true and let other
|
// No generic defined on "to"; therefore, return true and let other
|
||||||
// checks determine assignability
|
// checks determine assignability
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private recursive helper function to actually do the type-safe checking
|
* Private recursive helper function to actually do the type-safe checking
|
||||||
* of assignability.
|
* of assignability.
|
||||||
*/
|
*/
|
||||||
private static boolean isAssignableFrom(Type from, ParameterizedType to,
|
private static boolean isAssignableFrom(Type from, ParameterizedType to,
|
||||||
Map<String, Type> typeVarMap) {
|
Map<String, Type> typeVarMap) {
|
||||||
|
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to.equals(from)) {
|
if (to.equals(from)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First figure out the class and any type information.
|
// First figure out the class and any type information.
|
||||||
Class<?> clazz = $Gson$Types.getRawType(from);
|
Class<?> clazz = $Gson$Types.getRawType(from);
|
||||||
ParameterizedType ptype = null;
|
ParameterizedType ptype = null;
|
||||||
if (from instanceof ParameterizedType) {
|
if (from instanceof ParameterizedType) {
|
||||||
ptype = (ParameterizedType) from;
|
ptype = (ParameterizedType) from;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load up parameterized variable info if it was parameterized.
|
// Load up parameterized variable info if it was parameterized.
|
||||||
if (ptype != null) {
|
if (ptype != null) {
|
||||||
Type[] tArgs = ptype.getActualTypeArguments();
|
Type[] tArgs = ptype.getActualTypeArguments();
|
||||||
TypeVariable<?>[] tParams = clazz.getTypeParameters();
|
TypeVariable<?>[] tParams = clazz.getTypeParameters();
|
||||||
for (int i = 0; i < tArgs.length; i++) {
|
for (int i = 0; i < tArgs.length; i++) {
|
||||||
Type arg = tArgs[i];
|
Type arg = tArgs[i];
|
||||||
TypeVariable<?> var = tParams[i];
|
TypeVariable<?> var = tParams[i];
|
||||||
while (arg instanceof TypeVariable<?>) {
|
while (arg instanceof TypeVariable<?>) {
|
||||||
TypeVariable<?> v = (TypeVariable<?>) arg;
|
TypeVariable<?> v = (TypeVariable<?>) arg;
|
||||||
arg = typeVarMap.get(v.getName());
|
arg = typeVarMap.get(v.getName());
|
||||||
}
|
}
|
||||||
typeVarMap.put(var.getName(), arg);
|
typeVarMap.put(var.getName(), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if they are equivalent under our current mapping.
|
// check if they are equivalent under our current mapping.
|
||||||
if (typeEquals(ptype, to, typeVarMap)) {
|
if (typeEquals(ptype, to, typeVarMap)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Type itype : clazz.getGenericInterfaces()) {
|
for (Type itype : clazz.getGenericInterfaces()) {
|
||||||
if (isAssignableFrom(itype, to, new HashMap<String, Type>(typeVarMap))) {
|
if (isAssignableFrom(itype, to, new HashMap<String, Type>(typeVarMap))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interfaces didn't work, try the superclass.
|
// Interfaces didn't work, try the superclass.
|
||||||
Type sType = clazz.getGenericSuperclass();
|
Type sType = clazz.getGenericSuperclass();
|
||||||
return isAssignableFrom(sType, to, new HashMap<String, Type>(typeVarMap));
|
return isAssignableFrom(sType, to, new HashMap<String, Type>(typeVarMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if two parameterized types are exactly equal, under the variable
|
* Checks if two parameterized types are exactly equal, under the variable
|
||||||
* replacement described in the typeVarMap.
|
* replacement described in the typeVarMap.
|
||||||
*/
|
*/
|
||||||
private static boolean typeEquals(ParameterizedType from,
|
private static boolean typeEquals(ParameterizedType from,
|
||||||
ParameterizedType to, Map<String, Type> typeVarMap) {
|
ParameterizedType to, Map<String, Type> typeVarMap) {
|
||||||
if (from.getRawType().equals(to.getRawType())) {
|
if (from.getRawType().equals(to.getRawType())) {
|
||||||
Type[] fromArgs = from.getActualTypeArguments();
|
Type[] fromArgs = from.getActualTypeArguments();
|
||||||
Type[] toArgs = to.getActualTypeArguments();
|
Type[] toArgs = to.getActualTypeArguments();
|
||||||
for (int i = 0; i < fromArgs.length; i++) {
|
for (int i = 0; i < fromArgs.length; i++) {
|
||||||
if (!matches(fromArgs[i], toArgs[i], typeVarMap)) {
|
if (!matches(fromArgs[i], toArgs[i], typeVarMap)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AssertionError buildUnexpectedTypeError(
|
private static AssertionError buildUnexpectedTypeError(
|
||||||
Type token, Class<?>... expected) {
|
Type token, Class<?>... expected) {
|
||||||
|
|
||||||
// Build exception message
|
// Build exception message
|
||||||
StringBuilder exceptionMessage =
|
StringBuilder exceptionMessage =
|
||||||
new StringBuilder("Unexpected type. Expected one of: ");
|
new StringBuilder("Unexpected type. Expected one of: ");
|
||||||
for (Class<?> clazz : expected) {
|
for (Class<?> clazz : expected) {
|
||||||
exceptionMessage.append(clazz.getName()).append(", ");
|
exceptionMessage.append(clazz.getName()).append(", ");
|
||||||
}
|
}
|
||||||
exceptionMessage.append("but got: ").append(token.getClass().getName())
|
exceptionMessage.append("but got: ").append(token.getClass().getName())
|
||||||
.append(", for type token: ").append(token.toString()).append('.');
|
.append(", for type token: ").append(token.toString()).append('.');
|
||||||
|
|
||||||
return new AssertionError(exceptionMessage.toString());
|
return new AssertionError(exceptionMessage.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if two types are the same or are equivalent under a variable mapping
|
* Checks if two types are the same or are equivalent under a variable mapping
|
||||||
* given in the type map that was provided.
|
* given in the type map that was provided.
|
||||||
*/
|
*/
|
||||||
private static boolean matches(Type from, Type to, Map<String, Type> typeMap) {
|
private static boolean matches(Type from, Type to, Map<String, Type> typeMap) {
|
||||||
return to.equals(from)
|
return to.equals(from)
|
||||||
|| (from instanceof TypeVariable
|
|| (from instanceof TypeVariable
|
||||||
&& to.equals(typeMap.get(((TypeVariable<?>) from).getName())));
|
&& to.equals(typeMap.get(((TypeVariable<?>) from).getName())));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public final int hashCode() {
|
@Override public final int hashCode() {
|
||||||
return this.hashCode;
|
return this.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public final boolean equals(Object o) {
|
@Override public final boolean equals(Object o) {
|
||||||
return o instanceof TypeToken<?>
|
return o instanceof TypeToken<?>
|
||||||
&& $Gson$Types.equals(type, ((TypeToken<?>) o).type);
|
&& $Gson$Types.equals(type, ((TypeToken<?>) o).type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public final String toString() {
|
@Override public final String toString() {
|
||||||
return $Gson$Types.typeToString(type);
|
return $Gson$Types.typeToString(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets type literal for the given {@code Type} instance.
|
* Gets type literal for the given {@code Type} instance.
|
||||||
*/
|
*/
|
||||||
public static TypeToken<?> get(Type type) {
|
public static TypeToken<?> get(Type type) {
|
||||||
return new TypeToken<Object>(type);
|
return new TypeToken<Object>(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets type literal for the given {@code Class} instance.
|
* Gets type literal for the given {@code Class} instance.
|
||||||
*/
|
*/
|
||||||
public static <T> TypeToken<T> get(Class<T> type) {
|
public static <T> TypeToken<T> get(Class<T> type) {
|
||||||
return new TypeToken<T>(type);
|
return new TypeToken<T>(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* This package provides utility classes for finding type information for generic types.
|
* This package provides utility classes for finding type information for generic types.
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh, Joel Leitch
|
* @author Inderjeet Singh, Joel Leitch
|
||||||
*/
|
*/
|
||||||
package com.google.gson.reflect;
|
package com.google.gson.reflect;
|
||||||
|
|||||||
+1329
-1329
File diff suppressed because it is too large
Load Diff
@@ -1,71 +1,71 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Google Inc.
|
* Copyright (C) 2010 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.stream;
|
package com.google.gson.stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lexical scoping elements within a JSON reader or writer.
|
* Lexical scoping elements within a JSON reader or writer.
|
||||||
*
|
*
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
enum JsonScope {
|
enum JsonScope {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array with no elements requires no separators or newlines before
|
* An array with no elements requires no separators or newlines before
|
||||||
* it is closed.
|
* it is closed.
|
||||||
*/
|
*/
|
||||||
EMPTY_ARRAY,
|
EMPTY_ARRAY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A array with at least one value requires a comma and newline before
|
* A array with at least one value requires a comma and newline before
|
||||||
* the next element.
|
* the next element.
|
||||||
*/
|
*/
|
||||||
NONEMPTY_ARRAY,
|
NONEMPTY_ARRAY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object with no name/value pairs requires no separators or newlines
|
* An object with no name/value pairs requires no separators or newlines
|
||||||
* before it is closed.
|
* before it is closed.
|
||||||
*/
|
*/
|
||||||
EMPTY_OBJECT,
|
EMPTY_OBJECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object whose most recent element is a key. The next element must
|
* An object whose most recent element is a key. The next element must
|
||||||
* be a value.
|
* be a value.
|
||||||
*/
|
*/
|
||||||
DANGLING_NAME,
|
DANGLING_NAME,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object with at least one name/value pair requires a comma and
|
* An object with at least one name/value pair requires a comma and
|
||||||
* newline before the next element.
|
* newline before the next element.
|
||||||
*/
|
*/
|
||||||
NONEMPTY_OBJECT,
|
NONEMPTY_OBJECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No object or array has been started.
|
* No object or array has been started.
|
||||||
*/
|
*/
|
||||||
EMPTY_DOCUMENT,
|
EMPTY_DOCUMENT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A document with at an array or object.
|
* A document with at an array or object.
|
||||||
*/
|
*/
|
||||||
NONEMPTY_DOCUMENT,
|
NONEMPTY_DOCUMENT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A document that's been closed and cannot be accessed.
|
* A document that's been closed and cannot be accessed.
|
||||||
*/
|
*/
|
||||||
CLOSED,
|
CLOSED,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +1,85 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Google Inc.
|
* Copyright (C) 2010 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.stream;
|
package com.google.gson.stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A structure, name or value type in a JSON-encoded string.
|
* A structure, name or value type in a JSON-encoded string.
|
||||||
*
|
*
|
||||||
* @author Jesse Wilson
|
* @author Jesse Wilson
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
public enum JsonToken {
|
public enum JsonToken {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The opening of a JSON array. Written using {@link JsonWriter#beginObject}
|
* The opening of a JSON array. Written using {@link JsonWriter#beginObject}
|
||||||
* and read using {@link JsonReader#beginObject}.
|
* and read using {@link JsonReader#beginObject}.
|
||||||
*/
|
*/
|
||||||
BEGIN_ARRAY,
|
BEGIN_ARRAY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The closing of a JSON array. Written using {@link JsonWriter#endArray}
|
* The closing of a JSON array. Written using {@link JsonWriter#endArray}
|
||||||
* and read using {@link JsonReader#endArray}.
|
* and read using {@link JsonReader#endArray}.
|
||||||
*/
|
*/
|
||||||
END_ARRAY,
|
END_ARRAY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The opening of a JSON object. Written using {@link JsonWriter#beginObject}
|
* The opening of a JSON object. Written using {@link JsonWriter#beginObject}
|
||||||
* and read using {@link JsonReader#beginObject}.
|
* and read using {@link JsonReader#beginObject}.
|
||||||
*/
|
*/
|
||||||
BEGIN_OBJECT,
|
BEGIN_OBJECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The closing of a JSON object. Written using {@link JsonWriter#endObject}
|
* The closing of a JSON object. Written using {@link JsonWriter#endObject}
|
||||||
* and read using {@link JsonReader#endObject}.
|
* and read using {@link JsonReader#endObject}.
|
||||||
*/
|
*/
|
||||||
END_OBJECT,
|
END_OBJECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON property name. Within objects, tokens alternate between names and
|
* A JSON property name. Within objects, tokens alternate between names and
|
||||||
* their values. Written using {@link JsonWriter#name} and read using {@link
|
* their values. Written using {@link JsonWriter#name} and read using {@link
|
||||||
* JsonReader#nextName}
|
* JsonReader#nextName}
|
||||||
*/
|
*/
|
||||||
NAME,
|
NAME,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON string.
|
* A JSON string.
|
||||||
*/
|
*/
|
||||||
STRING,
|
STRING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON number represented in this API by a Java {@code double}, {@code
|
* A JSON number represented in this API by a Java {@code double}, {@code
|
||||||
* long}, or {@code int}.
|
* long}, or {@code int}.
|
||||||
*/
|
*/
|
||||||
NUMBER,
|
NUMBER,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON {@code true} or {@code false}.
|
* A JSON {@code true} or {@code false}.
|
||||||
*/
|
*/
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON {@code null}.
|
* A JSON {@code null}.
|
||||||
*/
|
*/
|
||||||
NULL,
|
NULL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The end of the JSON stream. This sentinel value is returned by {@link
|
* The end of the JSON stream. This sentinel value is returned by {@link
|
||||||
* JsonReader#peek()} to signal that the JSON-encoded value has no more
|
* JsonReader#peek()} to signal that the JSON-encoded value has no more
|
||||||
* tokens.
|
* tokens.
|
||||||
*/
|
*/
|
||||||
END_DOCUMENT
|
END_DOCUMENT
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,44 +1,44 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 Google Inc.
|
* Copyright (C) 2010 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.stream;
|
package com.google.gson.stream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when a reader encounters malformed JSON. Some syntax errors can be
|
* Thrown when a reader encounters malformed JSON. Some syntax errors can be
|
||||||
* ignored by calling {@link JsonReader#setLenient(boolean)}.
|
* ignored by calling {@link JsonReader#setLenient(boolean)}.
|
||||||
*/
|
*/
|
||||||
public final class MalformedJsonException extends IOException {
|
public final class MalformedJsonException extends IOException {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public MalformedJsonException(String msg) {
|
public MalformedJsonException(String msg) {
|
||||||
super(msg);
|
super(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MalformedJsonException(String msg, Throwable throwable) {
|
public MalformedJsonException(String msg, Throwable throwable) {
|
||||||
super(msg);
|
super(msg);
|
||||||
// Using initCause() instead of calling super() because Java 1.5 didn't retrofit IOException
|
// Using initCause() instead of calling super() because Java 1.5 didn't retrofit IOException
|
||||||
// with a constructor with Throwable. This was done in Java 1.6
|
// with a constructor with Throwable. This was done in Java 1.6
|
||||||
initCause(throwable);
|
initCause(throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MalformedJsonException(Throwable throwable) {
|
public MalformedJsonException(Throwable throwable) {
|
||||||
// Using initCause() instead of calling super() because Java 1.5 didn't retrofit IOException
|
// Using initCause() instead of calling super() because Java 1.5 didn't retrofit IOException
|
||||||
// with a constructor with Throwable. This was done in Java 1.6
|
// with a constructor with Throwable. This was done in Java 1.6
|
||||||
initCause(throwable);
|
initCause(throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Google Inc.
|
* Copyright (C) 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.gson.stream;
|
package com.google.gson.stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pool of string instances. Unlike the {@link String#intern() VM's
|
* A pool of string instances. Unlike the {@link String#intern() VM's
|
||||||
* interned strings}, this pool provides no guarantee of reference equality.
|
* interned strings}, this pool provides no guarantee of reference equality.
|
||||||
* It is intended only to save allocations. This class is not thread safe.
|
* It is intended only to save allocations. This class is not thread safe.
|
||||||
*/
|
*/
|
||||||
final class StringPool {
|
final class StringPool {
|
||||||
|
|
||||||
private final String[] pool = new String[512];
|
private final String[] pool = new String[512];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string equal to {@code new String(array, start, length)}.
|
* Returns a string equal to {@code new String(array, start, length)}.
|
||||||
*/
|
*/
|
||||||
public String get(char[] array, int start, int length) {
|
public String get(char[] array, int start, int length) {
|
||||||
// Compute an arbitrary hash of the content
|
// Compute an arbitrary hash of the content
|
||||||
int hashCode = 0;
|
int hashCode = 0;
|
||||||
for (int i = start; i < start + length; i++) {
|
for (int i = start; i < start + length; i++) {
|
||||||
hashCode = (hashCode * 31) + array[i];
|
hashCode = (hashCode * 31) + array[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick a bucket using Doug Lea's supplemental secondaryHash function (from HashMap)
|
// Pick a bucket using Doug Lea's supplemental secondaryHash function (from HashMap)
|
||||||
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
|
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
|
||||||
hashCode ^= (hashCode >>> 7) ^ (hashCode >>> 4);
|
hashCode ^= (hashCode >>> 7) ^ (hashCode >>> 4);
|
||||||
int index = hashCode & (pool.length - 1);
|
int index = hashCode & (pool.length - 1);
|
||||||
|
|
||||||
String pooled = pool[index];
|
String pooled = pool[index];
|
||||||
if (pooled == null || pooled.length() != length) {
|
if (pooled == null || pooled.length() != length) {
|
||||||
String result = new String(array, start, length);
|
String result = new String(array, start, length);
|
||||||
pool[index] = result;
|
pool[index] = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
if (pooled.charAt(i) != array[start + i]) {
|
if (pooled.charAt(i) != array[start + i]) {
|
||||||
String result = new String(array, start, length);
|
String result = new String(array, start, length);
|
||||||
pool[index] = result;
|
pool[index] = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pooled;
|
return pooled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class IOThreadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Thread lt = ThreadTool.makeVThreadIfSupport("数据包计时重发线程", () -> {
|
Thread lt = ThreadTool.makeVThreadIfSupport("数据包计时重发线程", () -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (AB.get()) {
|
while (AB.get()) {
|
||||||
@@ -57,7 +57,7 @@ public class IOThreadManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Thread ls = ThreadTool.makeVThreadIfSupport("本地发送线程", () -> {
|
Thread ls = ThreadTool.makeVThreadIfSupport("本地发送线程", () -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (AB.get()) {
|
while (AB.get()) {
|
||||||
@@ -77,7 +77,6 @@ public class IOThreadManager {
|
|||||||
sbk.number = 0;
|
sbk.number = 0;
|
||||||
sbk.command = 3;
|
sbk.command = 3;
|
||||||
klc.submitDataBlockNoDelay(sbk);
|
klc.submitDataBlockNoDelay(sbk);
|
||||||
e.printStackTrace();
|
|
||||||
}finally {
|
}finally {
|
||||||
try {
|
try {
|
||||||
tc.getDout().close();
|
tc.getDout().close();
|
||||||
@@ -86,7 +85,7 @@ public class IOThreadManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Thread lr = ThreadTool.makeVThreadIfSupport("本地接收线程", () -> {
|
Thread lr = ThreadTool.makeVThreadIfSupport("本地接收线程", () -> {
|
||||||
try {
|
try {
|
||||||
while (AB.get()) {
|
while (AB.get()) {
|
||||||
KLALBBlock ks = tc.packBlock();
|
KLALBBlock ks = tc.packBlock();
|
||||||
@@ -105,7 +104,6 @@ public class IOThreadManager {
|
|||||||
sbk.number = 0;
|
sbk.number = 0;
|
||||||
sbk.command = 3;
|
sbk.command = 3;
|
||||||
klc.submitDataBlockNoDelay(sbk);
|
klc.submitDataBlockNoDelay(sbk);
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
tc.getDin().close();
|
tc.getDin().close();
|
||||||
@@ -143,7 +141,7 @@ public class IOThreadManager {
|
|||||||
}
|
}
|
||||||
klc.getRemotetcps().add(tc);
|
klc.getRemotetcps().add(tc);
|
||||||
try {
|
try {
|
||||||
Thread rs = ThreadTool.makeVThreadIfSupport("远程发送线程", () -> {
|
Thread rs = ThreadTool.makeVThreadIfSupport("远程发送线程", () -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -151,17 +149,15 @@ public class IOThreadManager {
|
|||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Thread rr = ThreadTool.makeVThreadIfSupport("远程接收线程", () -> {
|
Thread rr = ThreadTool.makeVThreadIfSupport("远程接收线程", () -> {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
klc.remoteReceive(tc);
|
klc.remoteReceive(tc);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
rs.interrupt();
|
rs.interrupt();
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
rs.start();
|
rs.start();
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import org.kne.cloud.network.mport.IPPort;
|
|||||||
public class KLALBBlock implements Comparable<KLALBBlock>{
|
public class KLALBBlock implements Comparable<KLALBBlock>{
|
||||||
private static AtomicLong sng=new AtomicLong(1);
|
private static AtomicLong sng=new AtomicLong(1);
|
||||||
|
|
||||||
public long sn;//每个数据包的唯一编号
|
public long sn;//每个数据包的唯一编号
|
||||||
public int cuid;//用于识别数据包的stream ID号
|
public int cuid;//用于识别数据包的stream ID号
|
||||||
public long number;//数据包的编号,用于排序
|
public long number;//数据包的编号,用于排序
|
||||||
public byte[]data;//数据内容
|
public byte[]data;//数据内容
|
||||||
public int command;//功能标记 0=PING 1=PONG 2=SYN 3=RST
|
public int command;//功能标记 0=PING 1=PONG 2=SYN 3=RST
|
||||||
public long pingtime;//PING计时器
|
public long pingtime;//PING计时器
|
||||||
public int cacheused;
|
public int cacheused;
|
||||||
|
|
||||||
public String lservice;
|
public String lservice;
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ public class KLALBCM {
|
|||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
if(args.length==0){
|
if(args.length==0){
|
||||||
System.out.println("命令行参数输入服务器任意一条线路的地址:端口可以下载服务器线路列表");
|
System.out.println("命令行参数输入服务器任意一条线路的地址:端口可以下载服务器线路列表");
|
||||||
System.out.println("命令行参数输入服务器名称即可启动负载均衡");
|
System.out.println("命令行参数输入服务器名称即可启动负载均衡");
|
||||||
}else if(args.length==1) {
|
}else if(args.length==1) {
|
||||||
if(args[0].equals("-gui")) {
|
if(args[0].equals("-gui")) {
|
||||||
KLALBClientGUI.main(args);
|
KLALBClientGUI.main(args);
|
||||||
@@ -27,33 +27,35 @@ public class KLALBCM {
|
|||||||
File pdis=KLALBIPList.getSLdir(args[0]);
|
File pdis=KLALBIPList.getSLdir(args[0]);
|
||||||
File f=new File(pdis,"iplist.json");
|
File f=new File(pdis,"iplist.json");
|
||||||
if(f.exists()) {
|
if(f.exists()) {
|
||||||
System.out.println("加载线路列表:"+f);
|
System.out.println("加载线路列表:"+f);
|
||||||
byte[] bytes;
|
|
||||||
try {
|
try {
|
||||||
KLALBIPList.updateIPList(args[0]);
|
KLALBIPList.updateIPList(args[0]);
|
||||||
bytes = Files.readAllBytes(Paths.get(f.toURI()));
|
STJson stj=new STJson(new String(Files.readAllBytes(Paths.get(f.toURI()))));
|
||||||
STJson stj=new STJson(new String(bytes));
|
|
||||||
KLALBClient kc= new KLALBClient();
|
KLALBClient kc= new KLALBClient();
|
||||||
kc.getTls().addAll(stj.getTunnels());
|
kc.getTls().addAll(stj.getTunnels());
|
||||||
kc.connectTunnel();
|
kc.connectTunnel();
|
||||||
List<ServiceElement> lse=stj.getServices();
|
|
||||||
|
ProxyJson pj=new ProxyJson(new File(pdis,"services.json"), stj);
|
||||||
|
kc.getPet().addAll(pj.getPls());
|
||||||
|
kc.listenProxy();
|
||||||
|
/* List<ServiceElement> lse=stj.getServices();
|
||||||
for (Iterator<ServiceElement> iterator = lse.iterator(); iterator.hasNext();) {
|
for (Iterator<ServiceElement> iterator = lse.iterator(); iterator.hasNext();) {
|
||||||
ServiceElement serviceElement = (ServiceElement) iterator.next();
|
ServiceElement serviceElement = (ServiceElement) iterator.next();
|
||||||
ProxyIPPortProperties pippp=new ProxyIPPortProperties(pdis, serviceElement.name, "127.0.0.1", serviceElement.ipport.getPort());
|
ProxyIPPortProperties pippp=new ProxyIPPortProperties(pdis, serviceElement.name, "0.0.0.0", serviceElement.ipport.getPort());
|
||||||
try {
|
try {
|
||||||
kc.open(pippp.getBindPort(),serviceElement, pippp.getBindIP());
|
kc.open(pippp.getBindPort(),serviceElement, pippp.getBindIP());
|
||||||
}catch(BindException e) {
|
}catch(BindException e) {
|
||||||
System.out.println("打开端口失败:"+pippp.getBindIP()+" "+pippp.getBindPort());
|
System.out.println("打开端口失败:"+pippp.getBindIP()+" "+pippp.getBindPort());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
}catch (IOException e) {
|
}catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}else {
|
}else {
|
||||||
System.out.println("线路列表不存在");
|
System.out.println("线路列表不存在");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.swing.text.html.HTMLDocument.HTMLReader.PreAction;
|
||||||
|
|
||||||
import org.kne.cloud.network.mport.IPPort;
|
import org.kne.cloud.network.mport.IPPort;
|
||||||
import org.kne.cloud.network.mport.ServiceElement;
|
import org.kne.cloud.network.mport.ServiceElement;
|
||||||
import org.kne.cloud.network.mport.ThreadTool;
|
import org.kne.cloud.network.mport.ThreadTool;
|
||||||
@@ -37,19 +39,19 @@ public class KLALBClient {
|
|||||||
private IOThreadManager iom=new IOThreadManager();
|
private IOThreadManager iom=new IOThreadManager();
|
||||||
private List<Tunnel> tls=new ArrayList<>();
|
private List<Tunnel> tls=new ArrayList<>();
|
||||||
private List<TCPListener> tcpl=new ArrayList<>();
|
private List<TCPListener> tcpl=new ArrayList<>();
|
||||||
|
private List<ProxyElement> pet=new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
public void open(int port, ServiceElement sel,String bindip) throws IOException {
|
private void open(ProxyElement pe) throws IOException {
|
||||||
TCPListener tl=new TCPListener(port,bindip);
|
TCPListener tl=new TCPListener(pe.getIpport().getPort(),pe.getIpport().getIp());
|
||||||
tl.setCon((s)->{
|
tl.setCon((s)->{
|
||||||
LocalTCPConnection tcc = null;
|
LocalTCPConnection tcc = null;
|
||||||
try {
|
try {
|
||||||
tcc = new LocalTCPConnection(s);
|
tcc = new LocalTCPConnection(s);
|
||||||
tcc.setServiceElement(sel);
|
tcc.setServiceElement(pe.getSe());
|
||||||
//System.out.println("TCP:"+tcc.getCuid()+"已连接");
|
//System.out.println("TCP:"+tcc.getCuid()+"已连接");
|
||||||
iom.handleLocal(tcc,true);
|
iom.handleLocal(tcc,true);
|
||||||
//System.out.println("TCP:"+tcc.getCuid()+"已关闭");
|
//System.out.println("TCP:"+tcc.getCuid()+"已关闭");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}finally {
|
}finally {
|
||||||
@@ -60,12 +62,22 @@ public class KLALBClient {
|
|||||||
});
|
});
|
||||||
tl.open();
|
tl.open();
|
||||||
tcpl.add(tl);
|
tcpl.add(tl);
|
||||||
System.out.println(sel.name+"映射已启动 端口:"+port+" 绑定地址:"+bindip);
|
System.out.println(pe.getSe().name+"映射已启动 端口:"+pe.getIpport().getPort()+" 绑定地址:"+pe.getIpport().getIp());
|
||||||
|
}
|
||||||
|
public void listenProxy() {
|
||||||
|
for (int i = 0; i < pet.size(); i++) {
|
||||||
|
ProxyElement pe=pet.get(i);
|
||||||
|
try {
|
||||||
|
open(pe);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void connectTunnel() {
|
public void connectTunnel() {
|
||||||
for (int i = 0; i < tls.size(); i++) {
|
for (int i = 0; i < tls.size(); i++) {
|
||||||
Tunnel tll=tls.get(i);
|
Tunnel tll=tls.get(i);
|
||||||
ThreadTool.makeVThreadIfSupport("隧道监视线程", ()->{
|
ThreadTool.makeVThreadIfSupport("隧道监视线程", ()->{
|
||||||
int re=0;
|
int re=0;
|
||||||
RemoteTCPConnection tc=null;
|
RemoteTCPConnection tc=null;
|
||||||
while(iom.isOpen()) {
|
while(iom.isOpen()) {
|
||||||
@@ -84,10 +96,10 @@ public class KLALBClient {
|
|||||||
throw new EOFException();
|
throw new EOFException();
|
||||||
}
|
}
|
||||||
re=0;
|
re=0;
|
||||||
System.out.println(tll+":连接成功");
|
System.out.println(tll+":连接成功");
|
||||||
tll.setState(true);
|
tll.setState(true);
|
||||||
iom.handleRemote(tc);
|
iom.handleRemote(tc);
|
||||||
System.out.println(tll+":连接断开");
|
System.out.println(tll+":连接断开");
|
||||||
tll.setState(false);
|
tll.setState(false);
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -112,6 +124,9 @@ public class KLALBClient {
|
|||||||
public List<Tunnel> getTls() {
|
public List<Tunnel> getTls() {
|
||||||
return tls;
|
return tls;
|
||||||
}
|
}
|
||||||
|
public List<ProxyElement> getPet() {
|
||||||
|
return pet;
|
||||||
|
}
|
||||||
public List<ServiceElement> services=new ArrayList<ServiceElement>();
|
public List<ServiceElement> services=new ArrayList<ServiceElement>();
|
||||||
|
|
||||||
public List<ServiceElement> getServices() {
|
public List<ServiceElement> getServices() {
|
||||||
@@ -123,6 +138,9 @@ public class KLALBClient {
|
|||||||
TCPListener tl = (TCPListener) iterator.next();
|
TCPListener tl = (TCPListener) iterator.next();
|
||||||
tl.close();
|
tl.close();
|
||||||
}
|
}
|
||||||
|
tls.forEach((v)->{
|
||||||
|
v.destroyFrpc();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -85,13 +85,13 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentShown(ComponentEvent e) {
|
public void componentShown(ComponentEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentResized(ComponentEvent e) {
|
public void componentResized(ComponentEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentHidden(ComponentEvent e) {
|
public void componentHidden(ComponentEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -116,21 +116,21 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
JButton btnNewButton = new JButton("\u6DFB\u52A0");
|
JButton btnNewButton = new JButton("\u6DFB\u52A0");
|
||||||
btnNewButton.addActionListener(new ActionListener() {
|
btnNewButton.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
String s = JOptionPane.showInputDialog(KLALBClientGUI.this, "输入一条线路的地址");
|
String s = JOptionPane.showInputDialog(KLALBClientGUI.this, "输入一条线路的地址");
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
if (s.equals("")) {
|
if (s.equals("")) {
|
||||||
JOptionPane.showMessageDialog(KLALBClientGUI.this, "输入不能为空", "错误", JOptionPane.WARNING_MESSAGE);
|
JOptionPane.showMessageDialog(KLALBClientGUI.this, "输入不能为空", "错误", JOptionPane.WARNING_MESSAGE);
|
||||||
} else {
|
} else {
|
||||||
ProcessingFrame psf = new ProcessingFrame("正在下载线路列表");
|
ProcessingFrame psf = new ProcessingFrame("正在下载线路列表");
|
||||||
psf.setIconImage(bi);
|
psf.setIconImage(bi);
|
||||||
psf.getProgressBar().setIndeterminate(true);
|
psf.getProgressBar().setIndeterminate(true);
|
||||||
psf.setVisible(true);
|
psf.setVisible(true);
|
||||||
ThreadTool.makeVThreadIfSupport("线路列表获取", () -> {
|
ThreadTool.makeVThreadIfSupport("线路列表获取", () -> {
|
||||||
try {
|
try {
|
||||||
KLALBIPList.createIPList(s);
|
KLALBIPList.createIPList(s);
|
||||||
reloadCB();
|
reloadCB();
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
JOptionPane.showMessageDialog(KLALBClientGUI.this, e1.toString(), "错误",
|
JOptionPane.showMessageDialog(KLALBClientGUI.this, e1.toString(), "错误",
|
||||||
JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -152,7 +152,7 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
t=null;
|
t=null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t=ThreadTool.makeVThreadIfSupport("客户端主线程", () -> {
|
t=ThreadTool.makeVThreadIfSupport("客户端主线程", () -> {
|
||||||
btnNewButton_1.setEnabled(false);
|
btnNewButton_1.setEnabled(false);
|
||||||
comboBox.setEnabled(false);
|
comboBox.setEnabled(false);
|
||||||
String s = (String) comboBox.getSelectedItem();
|
String s = (String) comboBox.getSelectedItem();
|
||||||
@@ -162,12 +162,10 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
File pdis = KLALBIPList.getSLdir(s);
|
File pdis = KLALBIPList.getSLdir(s);
|
||||||
File f = new File(pdis, "iplist.json");
|
File f = new File(pdis, "iplist.json");
|
||||||
if (f.exists()) {
|
if (f.exists()) {
|
||||||
System.out.println("加载线路列表:" + f);
|
System.out.println("加载线路列表:" + f);;KLALBClient kc=null;
|
||||||
byte[] bytes;KLALBClient kc=null;
|
|
||||||
try {
|
try {
|
||||||
KLALBIPList.updateIPList(s);
|
KLALBIPList.updateIPList(s);
|
||||||
bytes = Files.readAllBytes(Paths.get(f.toURI()));
|
STJson stj=new STJson(new String(Files.readAllBytes(Paths.get(f.toURI()))));
|
||||||
STJson stj = new STJson(new String(bytes));
|
|
||||||
kc = new KLALBClient();
|
kc = new KLALBClient();
|
||||||
kc.getTls().addAll(stj.getTunnels());
|
kc.getTls().addAll(stj.getTunnels());
|
||||||
List<Tunnel>lt=kc.getTls();
|
List<Tunnel>lt=kc.getTls();
|
||||||
@@ -206,20 +204,13 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
ysp.repaint();
|
ysp.repaint();
|
||||||
repaint();
|
repaint();
|
||||||
kc.connectTunnel();
|
kc.connectTunnel();
|
||||||
List<ServiceElement> lse = stj.getServices();
|
|
||||||
for (Iterator<ServiceElement> iterator = lse.iterator(); iterator.hasNext();) {
|
ProxyJson pj=new ProxyJson(new File(pdis,"services.json"), stj);
|
||||||
ServiceElement serviceElement = (ServiceElement) iterator.next();
|
kc.getPet().addAll(pj.getPls());
|
||||||
ProxyIPPortProperties pippp = new ProxyIPPortProperties(pdis, serviceElement.name,
|
kc.listenProxy();
|
||||||
"0.0.0.0", serviceElement.ipport.getPort());
|
|
||||||
try {
|
|
||||||
kc.open(pippp.getBindPort(), serviceElement, pippp.getBindIP());
|
|
||||||
} catch (BindException e) {
|
|
||||||
System.out.println("打开端口失败:" + pippp.getBindIP() + " " + pippp.getBindPort());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
btnNewButton_1.setForeground(Color.RED);
|
btnNewButton_1.setForeground(Color.RED);
|
||||||
btnNewButton_1.setText("停止");
|
btnNewButton_1.setText("停止");
|
||||||
btnNewButton_1.setEnabled(true);
|
btnNewButton_1.setEnabled(true);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
@@ -234,7 +225,7 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
JOptionPane.showMessageDialog(KLALBClientGUI.this, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(KLALBClientGUI.this, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -246,17 +237,17 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("线路列表不存在");
|
System.out.println("线路列表不存在");
|
||||||
}
|
}
|
||||||
btnNewButton_1.setForeground(Color.GREEN);
|
btnNewButton_1.setForeground(Color.GREEN);
|
||||||
btnNewButton_1.setText("启动");
|
btnNewButton_1.setText("启动");
|
||||||
btnNewButton_1.setEnabled(true);
|
btnNewButton_1.setEnabled(true);
|
||||||
comboBox.setEnabled(true);
|
comboBox.setEnabled(true);
|
||||||
});t.start();
|
});t.start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
panel_1.add(btnNewButton_1, BorderLayout.EAST);
|
panel_1.add(btnNewButton_1, BorderLayout.EAST);
|
||||||
setTitle("KNE云网络负载均衡客户端");
|
setTitle("KNE云网络负载均衡客户端");
|
||||||
setSize(600, 370);
|
setSize(600, 370);
|
||||||
setLocationRelativeTo(null);
|
setLocationRelativeTo(null);
|
||||||
|
|
||||||
@@ -267,7 +258,7 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
TrayIcon ti = new TrayIcon(bi);
|
TrayIcon ti = new TrayIcon(bi);
|
||||||
ti.setImageAutoSize(true);
|
ti.setImageAutoSize(true);
|
||||||
PopupMenu jpm = new PopupMenu();
|
PopupMenu jpm = new PopupMenu();
|
||||||
MenuItem mi = new MenuItem("退出");
|
MenuItem mi = new MenuItem("退出");
|
||||||
mi.addActionListener(new ActionListener() {
|
mi.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -305,4 +296,4 @@ public class KLALBClientGUI extends XFrame {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new KLALBClientGUI();
|
new KLALBClientGUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ public class KLALBCore {
|
|||||||
for (int i = 0; i < l.size(); i++) {
|
for (int i = 0; i < l.size(); i++) {
|
||||||
KLALBBlock block=l.get(i);
|
KLALBBlock block=l.get(i);
|
||||||
long timex = (System.nanoTime() - block.sendtime) / 1000000;
|
long timex = (System.nanoTime() - block.sendtime) / 1000000;
|
||||||
if (timex > 100*(1<<Math.min(8,block.resend))+1000*i) {
|
if (timex > 200*(1<<Math.min(8,block.resend))+1000*i) {
|
||||||
submitDataBlock(block);
|
submitDataBlock(block);
|
||||||
block.sendtime = System.nanoTime();
|
block.sendtime = System.nanoTime();
|
||||||
block.resend++;
|
block.resend++;
|
||||||
@@ -284,7 +284,7 @@ public class KLALBCore {
|
|||||||
l.remove(i);
|
l.remove(i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
System.out.println("超时重传:"+block);
|
System.out.println("超时重传:"+block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class KLALBIPList {
|
|||||||
String json=KLALBIPList.searchTunnels(address);
|
String json=KLALBIPList.searchTunnels(address);
|
||||||
STJson stj=new STJson(json);
|
STJson stj=new STJson(json);
|
||||||
File f=new File(getSLdir(stj.getName()),"iplist.json");
|
File f=new File(getSLdir(stj.getName()),"iplist.json");
|
||||||
System.out.println("线路列表已保存到:"+f);
|
System.out.println("线路列表已保存到:"+f);
|
||||||
f.getParentFile().mkdirs();
|
f.getParentFile().mkdirs();
|
||||||
f.createNewFile();
|
f.createNewFile();
|
||||||
PrintStream ps=new PrintStream(f);
|
PrintStream ps=new PrintStream(f);
|
||||||
@@ -63,6 +63,6 @@ public class KLALBIPList {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new ConnectException("搜索地址失败");
|
throw new ConnectException("搜索地址失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ import org.kne.cloud.network.mport.ServiceElement;
|
|||||||
|
|
||||||
public class KLALBSM {
|
public class KLALBSM {
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
System.out.println("KNE云负载均衡调度软件服务端V0.1");
|
System.out.println("KNE云负载均衡调度软件服务端V0.1");
|
||||||
ServerPropties sp=new ServerPropties();
|
ServerPropties sp=new ServerPropties();
|
||||||
|
|
||||||
int remp=sp.getPort();
|
int remp=sp.getPort();
|
||||||
System.out.println("开放端口:"+remp);
|
System.out.println("开放端口:"+remp);
|
||||||
new KLALBServer(remp,new Supplier<String>() {
|
new KLALBServer(remp,new Supplier<String>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -37,7 +37,7 @@ public class KLALBSM {
|
|||||||
return sj;
|
return sj;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
System.out.println("提示:运行时输入reload可以重新加载配置文件,已经建立的TCP连接不受影响(暂不支持修改开放端口)");
|
System.out.println("提示:运行时输入reload可以重新加载配置文件,已经建立的TCP连接不受影响(暂不支持修改开放端口)");
|
||||||
Scanner scn2=new Scanner(System.in);
|
Scanner scn2=new Scanner(System.in);
|
||||||
while(true) {
|
while(true) {
|
||||||
String command=scn2.next();
|
String command=scn2.next();
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ public class KLALBServer {
|
|||||||
tcc.setTunnel(tll);
|
tcc.setTunnel(tll);
|
||||||
|
|
||||||
UUID uid=new UUID(din.readLong(),din.readLong());
|
UUID uid=new UUID(din.readLong(),din.readLong());
|
||||||
System.out.println(uid);
|
|
||||||
IOThreadManager nx = null;
|
IOThreadManager nx = null;
|
||||||
synchronized (tcpl) {
|
synchronized (tcpl) {
|
||||||
if(whm.containsKey(uid)) {
|
if(whm.containsKey(uid)) {
|
||||||
@@ -57,9 +56,14 @@ public class KLALBServer {
|
|||||||
IOThreadManager n1=nx;
|
IOThreadManager n1=nx;
|
||||||
nx.getCore().setAcceptSYN((b)->{
|
nx.getCore().setAcceptSYN((b)->{
|
||||||
try {
|
try {
|
||||||
|
STJson stj=new STJson(gjso.get());
|
||||||
|
if(!stj.checkSafety(b.lipport)) {
|
||||||
|
System.out.println("未授权的请求:"+b.lipport);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Socket soc=new Socket(b.lipport.getIp(),b.lipport.getPort());
|
Socket soc=new Socket(b.lipport.getIp(),b.lipport.getPort());
|
||||||
LocalTCPConnection ltc=new LocalTCPConnection(soc, b.cuid);
|
LocalTCPConnection ltc=new LocalTCPConnection(soc, b.cuid);
|
||||||
ThreadTool.makeVThreadIfSupport("局域网连接监视线程", ()->{
|
ThreadTool.makeVThreadIfSupport("局域网连接监视线程", ()->{
|
||||||
try {
|
try {
|
||||||
n1.handleLocal(ltc, false);
|
n1.handleLocal(ltc, false);
|
||||||
}finally {
|
}finally {
|
||||||
@@ -68,7 +72,7 @@ public class KLALBServer {
|
|||||||
}).start();
|
}).start();
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("连接本地服务"+b.lipport+"失败,请检查你的本地服务");
|
System.out.println("连接本地服务"+b.lipport+"失败,请检查你的本地服务");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package org.kne.cloud.network.klalb;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.kne.cloud.network.mport.IPPort;
|
||||||
|
import org.kne.cloud.network.mport.ServiceElement;
|
||||||
|
|
||||||
|
public class ProxyElement {
|
||||||
|
private ServiceElement se;
|
||||||
|
private IPPort ipport;
|
||||||
|
public ServiceElement getSe() {
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
public IPPort getIpport() {
|
||||||
|
return ipport;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(ipport, se);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
ProxyElement other = (ProxyElement) obj;
|
||||||
|
return Objects.equals(ipport, other.ipport) && Objects.equals(se, other.se);
|
||||||
|
}
|
||||||
|
public ProxyElement(ServiceElement se, IPPort ipport) {
|
||||||
|
super();
|
||||||
|
this.se = se;
|
||||||
|
this.ipport = ipport;
|
||||||
|
}
|
||||||
|
public ProxyElement() {
|
||||||
|
}
|
||||||
|
public void setSe(ServiceElement se) {
|
||||||
|
this.se = se;
|
||||||
|
}
|
||||||
|
public void setIpport(IPPort ipport) {
|
||||||
|
this.ipport = ipport;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package org.kne.cloud.network.klalb;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import org.kne.cloud.network.mport.IPPort;
|
||||||
|
import org.kne.cloud.network.mport.ServiceElement;
|
||||||
|
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
|
public class ProxyJson {
|
||||||
|
private File f;
|
||||||
|
private List<ProxyElement> pls=new ArrayList<>();
|
||||||
|
public List<ProxyElement> getPls() {
|
||||||
|
return pls;
|
||||||
|
}
|
||||||
|
public ProxyJson(File f,STJson def) throws IOException {
|
||||||
|
super();
|
||||||
|
this.f = f;
|
||||||
|
if(!f.exists()||f.length()==0l) {
|
||||||
|
f.createNewFile();
|
||||||
|
JsonWriter jw=null;
|
||||||
|
try {
|
||||||
|
jw=new JsonWriter(new FileWriter(f));
|
||||||
|
jw.setIndent(" ");
|
||||||
|
jw.beginObject();
|
||||||
|
jw.name("services");
|
||||||
|
jw.beginArray();
|
||||||
|
for (Iterator<ServiceElement> iterator = def.getServices().iterator(); iterator.hasNext();) {
|
||||||
|
ServiceElement proxye = (ServiceElement) iterator.next();
|
||||||
|
jw.beginObject();
|
||||||
|
jw.name("name");
|
||||||
|
jw.value(proxye.name);
|
||||||
|
jw.name("protocol");
|
||||||
|
jw.value(proxye.protocol);
|
||||||
|
jw.name("localaddress");
|
||||||
|
jw.value(proxye.ipport.toString());
|
||||||
|
jw.name("bindaddress");
|
||||||
|
jw.value("0.0.0.0:"+proxye.ipport.getPort());
|
||||||
|
jw.endObject();
|
||||||
|
}
|
||||||
|
jw.endArray();
|
||||||
|
jw.endObject();
|
||||||
|
}finally{
|
||||||
|
if(jw!=null)
|
||||||
|
jw.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsonReader jr=null;
|
||||||
|
try {
|
||||||
|
jr=new JsonReader(new FileReader(f));
|
||||||
|
jr.beginObject();
|
||||||
|
while(jr.hasNext()) {
|
||||||
|
String name=jr.nextName();
|
||||||
|
switch(name) {
|
||||||
|
case "services":
|
||||||
|
jr.beginArray();
|
||||||
|
while(jr.hasNext()) {
|
||||||
|
jr.beginObject();
|
||||||
|
ProxyElement pe=new ProxyElement();
|
||||||
|
ServiceElement se=new ServiceElement();
|
||||||
|
pe.setSe(se);
|
||||||
|
while(jr.hasNext()) {
|
||||||
|
String n3=jr.nextName();
|
||||||
|
switch(n3) {
|
||||||
|
case "name":
|
||||||
|
se.name=jr.nextString();
|
||||||
|
break;
|
||||||
|
case "protocol":
|
||||||
|
se.protocol=jr.nextString();
|
||||||
|
break;
|
||||||
|
case "localaddress":
|
||||||
|
se.ipport=new IPPort (jr.nextString());
|
||||||
|
break;
|
||||||
|
case "bindaddress":
|
||||||
|
pe.setIpport(new IPPort (jr.nextString()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jr.skipValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pls.add(pe);
|
||||||
|
jr.endObject();
|
||||||
|
}
|
||||||
|
jr.endArray();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jr.skipValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jr.endObject();
|
||||||
|
}finally {
|
||||||
|
if(jr!=null)
|
||||||
|
jr.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -61,6 +61,16 @@ public class STJson {
|
|||||||
t.setName(sr.nextString());
|
t.setName(sr.nextString());
|
||||||
} else if (n2.equals("remoteaddress")) {
|
} else if (n2.equals("remoteaddress")) {
|
||||||
t.setIpport(new IPPort( sr.nextString()));
|
t.setIpport(new IPPort( sr.nextString()));
|
||||||
|
} else if (n2.equals("frpc")) {
|
||||||
|
StringBuilder sbd=new StringBuilder();
|
||||||
|
sr.beginArray();
|
||||||
|
while(sr.hasNext()) {
|
||||||
|
sbd.append(sr.nextString());
|
||||||
|
sbd.append('\r');
|
||||||
|
sbd.append('\n');
|
||||||
|
}
|
||||||
|
sr.endArray();
|
||||||
|
t.setFrpc(sbd.toString());
|
||||||
} else{
|
} else{
|
||||||
sr.skipValue();
|
sr.skipValue();
|
||||||
}
|
}
|
||||||
@@ -81,4 +91,14 @@ public class STJson {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean checkSafety(IPPort lipport) {
|
||||||
|
for (Iterator iterator = services.iterator(); iterator.hasNext();) {
|
||||||
|
ServiceElement serviceElement = (ServiceElement) iterator.next();
|
||||||
|
if(lipport.equals(serviceElement.ipport)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,21 +32,21 @@ public class TCPConnection {
|
|||||||
if (din != null)
|
if (din != null)
|
||||||
din.close();
|
din.close();
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
// TODO 自动生成的 catch 块
|
// TODO 自动生成的 catch 块
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (dout != null)
|
if (dout != null)
|
||||||
dout.close();
|
dout.close();
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
// TODO 自动生成的 catch 块
|
// TODO 自动生成的 catch 块
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (connect != null)
|
if (connect != null)
|
||||||
connect.close();
|
connect.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO 自动生成的 catch 块
|
// TODO 自动生成的 catch 块
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
connect = null;
|
connect = null;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class TCPListener {
|
|||||||
while(flag){
|
while(flag){
|
||||||
try {
|
try {
|
||||||
Socket soce=servers.accept();
|
Socket soce=servers.accept();
|
||||||
ThreadTool.makeVThreadIfSupport("śËżÚźŕĚýĎßłĚ",()->{
|
ThreadTool.makeVThreadIfSupport("端口监听线程",()->{
|
||||||
con.accept(soce);
|
con.accept(soce);
|
||||||
}).start();
|
}).start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ public class TPanel extends JPanel{
|
|||||||
setLayout(new BorderLayout(0, 0));
|
setLayout(new BorderLayout(0, 0));
|
||||||
|
|
||||||
tname = new JLabel(name);
|
tname = new JLabel(name);
|
||||||
tname.setFont(new Font("ËÎÌå", Font.BOLD, 20));
|
tname.setFont(new Font("宋体", Font.BOLD, 20));
|
||||||
add(tname, BorderLayout.WEST);
|
add(tname, BorderLayout.WEST);
|
||||||
|
|
||||||
targ = new JLabel();
|
targ = new JLabel();
|
||||||
targ.setFont(new Font("ËÎÌå", Font.PLAIN, 13));
|
targ.setFont(new Font("宋体", Font.PLAIN, 13));
|
||||||
targ.setHorizontalAlignment(SwingConstants.TRAILING);
|
targ.setHorizontalAlignment(SwingConstants.TRAILING);
|
||||||
targ.setForeground(Color.YELLOW);
|
targ.setForeground(Color.YELLOW);
|
||||||
add(targ, BorderLayout.CENTER);
|
add(targ, BorderLayout.CENTER);
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package org.kne.cloud.network.klalb;
|
|||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
@@ -19,6 +22,7 @@ import java.util.Set;
|
|||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
@@ -30,6 +34,34 @@ import org.kne.cloud.network.mport.IPPort;
|
|||||||
public class Tunnel{
|
public class Tunnel{
|
||||||
private String name;
|
private String name;
|
||||||
private IPPort ipport;
|
private IPPort ipport;
|
||||||
|
private String frpc;
|
||||||
|
public String getFrpc() {
|
||||||
|
return frpc;
|
||||||
|
}
|
||||||
|
private Thread hook;
|
||||||
|
public void setFrpc(String frpc) {
|
||||||
|
this.frpc = frpc;
|
||||||
|
if(frpc!=null&&hook==null) {
|
||||||
|
hook=new Thread(()->{
|
||||||
|
finalize();
|
||||||
|
});
|
||||||
|
Runtime.getRuntime().addShutdownHook(hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void finalize() {
|
||||||
|
if(hook!=null) {
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().removeShutdownHook(hook);
|
||||||
|
}catch(Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
if(p!=null) {
|
||||||
|
System.out.println("frpc已关闭");
|
||||||
|
p.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private boolean state=false;
|
private boolean state=false;
|
||||||
|
|
||||||
private TListener tlr;
|
private TListener tlr;
|
||||||
@@ -87,9 +119,62 @@ public class Tunnel{
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return getName()+"$"+getIpport()+" "+delay/1000000;
|
return getName()+"$"+getIpport()+" "+delay/1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private volatile Process p=null;
|
||||||
public Socket connectClientSocket() throws UnknownHostException, IOException {
|
public Socket connectClientSocket() throws UnknownHostException, IOException {
|
||||||
|
if(frpc!=null) {
|
||||||
|
File f=new File("frpc");
|
||||||
|
f.mkdirs();
|
||||||
|
File inif=new File(f,"frpc.ini");
|
||||||
|
inif.createNewFile();
|
||||||
|
PrintStream ps=new PrintStream(inif);
|
||||||
|
ps.print(frpc);
|
||||||
|
ps.close();
|
||||||
|
AtomicBoolean ab=new AtomicBoolean(false);
|
||||||
|
Object lock=new Object();
|
||||||
|
if(p==null)
|
||||||
|
new Thread(()->{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
p = Runtime.getRuntime().exec("./frpc/frpc_windows_386.exe",null,f);
|
||||||
|
|
||||||
|
|
||||||
|
BufferedReader brd=new BufferedReader(new InputStreamReader( p.getInputStream()));
|
||||||
|
while(true) {
|
||||||
|
String r=brd.readLine();
|
||||||
|
if(r==null)
|
||||||
|
break;
|
||||||
|
System.err.println(r);
|
||||||
|
if(r.contains("start visitor success")) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ab.set(true);
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ab.get()) {
|
||||||
|
throw new IOException("frpc ERROR");
|
||||||
|
}
|
||||||
|
}
|
||||||
Socket socket=new Socket();
|
Socket socket=new Socket();
|
||||||
// socket.bind(new InetSocketAddress(new Random().nextInt(65535)+1));
|
|
||||||
socket.connect(getIpport().getSocketAddress(), Consts.CONNECT_TIMEOUT);
|
socket.connect(getIpport().getSocketAddress(), Consts.CONNECT_TIMEOUT);
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
@@ -140,22 +225,27 @@ public class Tunnel{
|
|||||||
public AtomicLong getIM() {
|
public AtomicLong getIM() {
|
||||||
return im;
|
return im;
|
||||||
}
|
}
|
||||||
PrintStream ndbg=null;
|
/*PrintStream ndbg=null;
|
||||||
private void initcdbg() {
|
private void initcdbg() {
|
||||||
try {
|
try {
|
||||||
ndbg=new PrintStream(name+".csv");
|
ndbg=new PrintStream(name+".csv");
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
public void updateTraffics(long timems) {
|
public void updateTraffics(long timems) {
|
||||||
tlr.setTraffic(om.get(), im.get(), om.get()-om1, im.get()-im1);
|
tlr.setTraffic(om.get(), im.get(), om.get()-om1, im.get()-im1);
|
||||||
|
/*
|
||||||
if(ndbg==null)
|
if(ndbg==null)
|
||||||
initcdbg();
|
initcdbg();
|
||||||
ndbg.println((om.get()-om1)+ (im.get()-im1)+","+delay);
|
ndbg.println((om.get()-om1)+ (im.get()-im1)+","+delay);
|
||||||
|
*/
|
||||||
om1=om.get();
|
om1=om.get();
|
||||||
im1=im.get();
|
im1=im.get();
|
||||||
}
|
}
|
||||||
|
public void destroyFrpc() {
|
||||||
|
if(p!=null) {
|
||||||
|
p.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ public class PortMultiUse {
|
|||||||
}
|
}
|
||||||
Scanner scn=new Scanner(f);
|
Scanner scn=new Scanner(f);
|
||||||
int remp=scn.nextInt();
|
int remp=scn.nextInt();
|
||||||
System.out.println("端口复用程序V0.2");
|
System.out.println("端口复用程序V0.2");
|
||||||
System.out.println("开放端口:"+remp);
|
System.out.println("开放端口:"+remp);
|
||||||
while(scn.hasNext() ) {
|
while(scn.hasNext() ) {
|
||||||
String s=scn.next();
|
String s=scn.next();
|
||||||
ServiceElement se=new ServiceElement(s);
|
ServiceElement se=new ServiceElement(s);
|
||||||
@@ -32,7 +32,7 @@ public class PortMultiUse {
|
|||||||
}
|
}
|
||||||
scn.close();
|
scn.close();
|
||||||
new PortRelay(remp,services).start();
|
new PortRelay(remp,services).start();
|
||||||
System.out.println("提示:运行时输入reload可以重新加载配置文件,已经建立的TCP连接不受影响(暂不支持修改开放端口)");
|
System.out.println("提示:运行时输入reload可以重新加载配置文件,已经建立的TCP连接不受影响(暂不支持修改开放端口)");
|
||||||
Scanner scn2=new Scanner(System.in);
|
Scanner scn2=new Scanner(System.in);
|
||||||
while(true) {
|
while(true) {
|
||||||
String command=scn2.next();
|
String command=scn2.next();
|
||||||
@@ -56,16 +56,16 @@ public class PortMultiUse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void ept() {
|
private static void ept() {
|
||||||
System.out.println("请填写配置文件后再启动程序!");
|
System.out.println("请填写配置文件后再启动程序!");
|
||||||
System.out.println("格式:");
|
System.out.println("格式:");
|
||||||
System.out.println("开放端口");
|
System.out.println("开放端口");
|
||||||
System.out.println("服务协议1$服务地址1$服务端口1");
|
System.out.println("服务协议1$服务地址1$服务端口1");
|
||||||
System.out.println("服务协议2$服务地址2$服务端口2");
|
System.out.println("服务协议2$服务地址2$服务端口2");
|
||||||
System.out.println("......");
|
System.out.println("......");
|
||||||
System.out.println("服务协议n$服务地址n$服务端口n");
|
System.out.println("服务协议n$服务地址n$服务端口n");
|
||||||
System.out.println("默认服务地址$默认服务端口");
|
System.out.println("默认服务地址$默认服务端口");
|
||||||
System.out.println("");
|
System.out.println("");
|
||||||
System.out.println("按照顺序从上向下匹配,若都不是则匹配最后一个");
|
System.out.println("按照顺序从上向下匹配,若都不是则匹配最后一个");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class PortRelay {
|
|||||||
this.services = services;
|
this.services = services;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
ssc=new TCPListener(port);
|
ssc=new TCPListener(port);
|
||||||
System.out.println("已打开端口:" + port);
|
System.out.println("已打开端口:" + port);
|
||||||
}
|
}
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
ssc.setCon((s)->{
|
ssc.setCon((s)->{
|
||||||
@@ -44,7 +44,7 @@ public class PortRelay {
|
|||||||
dinl=xdinl;
|
dinl=xdinl;
|
||||||
final DataOutputStream xdoutl =new DataOutputStream(sl.getOutputStream());
|
final DataOutputStream xdoutl =new DataOutputStream(sl.getOutputStream());
|
||||||
doutl=xdoutl;
|
doutl=xdoutl;
|
||||||
Thread tl=ThreadTool.makeVThreadIfSupport("远程->本地 转发线程", ()->{
|
Thread tl=ThreadTool.makeVThreadIfSupport("远程->本地 转发线程", ()->{
|
||||||
try {
|
try {
|
||||||
xdoutl.writeShort(n);
|
xdoutl.writeShort(n);
|
||||||
int len;
|
int len;
|
||||||
@@ -67,7 +67,7 @@ public class PortRelay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Thread tr=ThreadTool.makeVThreadIfSupport("本地->远程 转发线程", ()->{
|
Thread tr=ThreadTool.makeVThreadIfSupport("本地->远程 转发线程", ()->{
|
||||||
try {
|
try {
|
||||||
int len;
|
int len;
|
||||||
byte[]b=new byte[8192];
|
byte[]b=new byte[8192];
|
||||||
@@ -80,7 +80,7 @@ public class PortRelay {
|
|||||||
try {
|
try {
|
||||||
xdinl.close();
|
xdinl.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO 自动生成的 catch 块
|
// TODO 自动生成的 catch 块
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
if(xdout!=null)
|
if(xdout!=null)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class ServiceElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public ServiceElement() {
|
public ServiceElement() {
|
||||||
// TODO 自动生成的构造函数存根
|
// TODO 自动生成的构造函数存根
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class TCPListener {
|
|||||||
while(flag){
|
while(flag){
|
||||||
try {
|
try {
|
||||||
Socket soce=servers.accept();
|
Socket soce=servers.accept();
|
||||||
ThreadTool.makeVThreadIfSupport("śËżÚźŕĚýĎßłĚ",()->{
|
ThreadTool.makeVThreadIfSupport("端口监听线程",()->{
|
||||||
con.accept(soce);
|
con.accept(soce);
|
||||||
}).start();
|
}).start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class ThreadTool {
|
|||||||
}catch(Throwable e) {
|
}catch(Throwable e) {
|
||||||
//e.printStackTrace();
|
//e.printStackTrace();
|
||||||
if(first) {
|
if(first) {
|
||||||
System.out.println("请使用java19以上版本以提高性能!");
|
System.out.println("请使用java19以上版本以提高性能!");
|
||||||
first=false;
|
first=false;
|
||||||
}
|
}
|
||||||
return new Thread(r, name);
|
return new Thread(r, name);
|
||||||
|
|||||||
+31
-31
@@ -31,7 +31,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,19 +51,19 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(MouseEvent e) {
|
public void mouseExited(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(MouseEvent e) {
|
public void mouseEntered(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -172,7 +172,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +310,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,25 +378,25 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(MouseEvent e) {
|
public void mouseEntered(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(MouseEvent e) {
|
public void mouseExited(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -436,25 +436,25 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(MouseEvent e) {
|
public void mouseEntered(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(MouseEvent e) {
|
public void mouseExited(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -474,31 +474,31 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e) {
|
public void mouseReleased(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(MouseEvent e) {
|
public void mouseExited(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(MouseEvent e) {
|
public void mouseEntered(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
int s=XFrame.this.getExtendedState();
|
int s=XFrame.this.getExtendedState();
|
||||||
if(s!=JFrame.ICONIFIED) {
|
if(s!=JFrame.ICONIFIED) {
|
||||||
state=s;
|
state=s;
|
||||||
@@ -513,7 +513,7 @@ public class XFrame extends JFrame {
|
|||||||
titlelabel = new JLabel();
|
titlelabel = new JLabel();
|
||||||
sl_titlepanel.putConstraint(SpringLayout.WEST, titlelabel, 31, SpringLayout.WEST, titlepanel);
|
sl_titlepanel.putConstraint(SpringLayout.WEST, titlelabel, 31, SpringLayout.WEST, titlepanel);
|
||||||
sl_titlepanel.putConstraint(SpringLayout.EAST, titlelabel, -31, SpringLayout.EAST, titlepanel);
|
sl_titlepanel.putConstraint(SpringLayout.EAST, titlelabel, -31, SpringLayout.EAST, titlepanel);
|
||||||
titlelabel.setFont(new Font("宋体", Font.PLAIN, 16));
|
titlelabel.setFont(new Font("宋体", Font.PLAIN, 16));
|
||||||
sl_titlepanel.putConstraint(SpringLayout.NORTH, titlelabel, 0, SpringLayout.NORTH, titlepanel);
|
sl_titlepanel.putConstraint(SpringLayout.NORTH, titlelabel, 0, SpringLayout.NORTH, titlepanel);
|
||||||
sl_titlepanel.putConstraint(SpringLayout.SOUTH, titlelabel, 0, SpringLayout.SOUTH, titlepanel);
|
sl_titlepanel.putConstraint(SpringLayout.SOUTH, titlelabel, 0, SpringLayout.SOUTH, titlepanel);
|
||||||
titlelabel.setOpaque(false);
|
titlelabel.setOpaque(false);
|
||||||
@@ -528,13 +528,13 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowOpened(WindowEvent e) {
|
public void windowOpened(WindowEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowIconified(WindowEvent e) {
|
public void windowIconified(WindowEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,25 +546,25 @@ public class XFrame extends JFrame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowDeactivated(WindowEvent e) {
|
public void windowDeactivated(WindowEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowClosing(WindowEvent e) {
|
public void windowClosing(WindowEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowClosed(WindowEvent e) {
|
public void windowClosed(WindowEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowActivated(WindowEvent e) {
|
public void windowActivated(WindowEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -102,13 +102,13 @@ settings.addContainerListener(new ContainerListener() {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentMoved(ComponentEvent e) {
|
public void componentMoved(ComponentEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentHidden(ComponentEvent e) {
|
public void componentHidden(ComponentEvent e) {
|
||||||
// TODO 自动生成的方法存根
|
// TODO 自动生成的方法存根
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class UIEnv {
|
|||||||
} catch (FontFormatException e1) {
|
} catch (FontFormatException e1) {
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
// TODO 自动生成的 catch 块
|
// TODO 自动生成的 catch 块
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user