class MyMapTypeAdapterFactory() : TypeAdapterFactory {
override fun <T : Any?> create(gson: Gson, typeToken: TypeToken<T>): TypeAdapter<T>? {
val type = typeToken.getType()
val rawType = typeToken.getRawType()
return if (!Map::class.java.isAssignableFrom(rawType)) {
null
} else Adapter(gson) as TypeAdapter<T>
}
class Adapter(): TypeAdapter<Map<String, Any>>()
{
private var keyTypeAdapter: TypeAdapter<String> = TypeAdapters.STRING
private lateinit var valueTypeAdapter: TypeAdapter<Any>
constructor(gson: Gson): this()
{
valueTypeAdapter = MyObjectTypeAdapter(gson)
}
override fun read(`in`: JsonReader): Map<String, Any>? {
val peek = `in`.peek()
if (peek == JsonToken.NULL) {
`in`.nextNull()
return null
}
val map = mutableMapOf<String, Any>()
if (peek == JsonToken.BEGIN_ARRAY) {
`in`.beginArray()
while (`in`.hasNext()) {
`in`.beginArray() // entry array
val key = keyTypeAdapter.read(`in`)
val value = valueTypeAdapter.read(`in`)
val replaced = map.put(key, value)
if (replaced != null) {
throw JsonSyntaxException("duplicate key: $key")
}
`in`.endArray()
}
`in`.endArray()
} else {
`in`.beginObject()
while (`in`.hasNext()) {
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(`in`)
val key = keyTypeAdapter.read(`in`)
val value = valueTypeAdapter.read(`in`)
val replaced = map.put(key, value)
if (replaced != null) {
throw JsonSyntaxException("duplicate key: $key")
}
}
`in`.endObject()
}
return map
}
override fun write(out: JsonWriter, map: Map<String, Any>?) {
if (map == null) {
out.nullValue()
return
}
out.beginObject()
for ((key, value) in map) {
out.name(key)
valueTypeAdapter.write(out, value)
}
out.endObject()
return
}
}
class MyObjectTypeAdapter(var gson: Gson) : TypeAdapter<Any>()
{
override fun read(`in`: JsonReader): Any? {
val token = `in`.peek()
when (token) {
JsonToken.BEGIN_ARRAY -> {
val list = ArrayList<Any?>()
`in`.beginArray()
while (`in`.hasNext()) {
list.add(read(`in`))
}
`in`.endArray()
return list
}
JsonToken.BEGIN_OBJECT -> {
val map = LinkedTreeMap<String, Any>()
`in`.beginObject()
while (`in`.hasNext()) {
map[`in`.nextName()] = read(`in`)
}
`in`.endObject()
return map
}
JsonToken.STRING -> return `in`.nextString()
JsonToken.NUMBER -> //return `in`.nextDouble()
{
val strNumber = `in`.nextString()
return if(strNumber.contains('.')) {
strNumber.double()
} else {
strNumber.int()
}
}
JsonToken.BOOLEAN -> return `in`.nextBoolean()
JsonToken.NULL -> {
`in`.nextNull()
return null
}
else -> throw IllegalStateException()
}
}
override fun write(out: JsonWriter, value: Any?) {
if (value == null) {
out.nullValue()
return
}
val typeAdapter = gson.getAdapter(value.javaClass) as TypeAdapter<Any>
if (typeAdapter is ObjectTypeAdapter) {
out.beginObject()
out.endObject()
return
}
typeAdapter.write(out, value)
}
}
}
spring注入
添加工厂类
object GsonUtils {
@JvmStatic
fun getGson(): Gson
{
return GsonBuilder().setDateFormat("yyyy'-'MM'-'dd HH':'mm':'ss").registerTypeAdapterFactory(MyMapTypeAdapterFactory()).create()
}
}
xml注入
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.GsonHttpMessageConverter" >
<property name="gson">
<bean class="com.example.GsonUtils" factory-method="getGson" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>