1、通过 JsonClass 解析 Kotlin
// build.gradle 依赖
id 'kotlin-kapt'
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.14.0'
// @JsonClass 注解
@JsonClass(generateAdapter = true) data class PlantParserData(
val plantId: String,
val name: String,
val description: String,
val growZoneNumber: Int,
val wateringInterval: Int,
val imageUrl: String,
)
fun parserJsonClass() {
val moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<PlantParserData> = moshi.adapter(PlantParserData::class.java)
val jsonData = jsonAdapter.fromJson(dataKotlinParser)
log(jsonData.toString())
log(jsonAdapter.toJson(jsonData))
}
2、通过 KotlinJsonAdapterFactory 解析 Kotlin
// build.gradle 依赖
implementation "com.squareup.moshi:moshi-kotlin:1.14.0"
data class PlantKotlinData(
val plantId: String,
val name: String,
val description: String,
val growZoneNumber: Int,
val wateringInterval: Int,
val imageUrl: String,
)
fun parserKotlinData() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter: JsonAdapter<PlantKotlinData> = moshi.adapter(PlantKotlinData::class.java)
val jsonData = jsonAdapter.fromJson(dataKotlinParser)
log(jsonData.toString())
log(jsonAdapter.toJson(jsonData))
}
3、newParameterizedType 解析 List
fun parserJsonList(){
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val plantListType = Types.newParameterizedType(List::class.java, PlantKotlinData::class.java)
val plantListAdapter = moshi.adapter<List<PlantKotlinData>>(plantListType)
val plantList = plantListAdapter.fromJson(dataList) ?: emptyList()
log(plantList.toString())
log(plantListAdapter.toJson(plantList))
}
4、indent 格式化打印
fun printPretty() {
val plant = PlantKotlinData(
"coriandrum-sativum",
"Cilantro",
"Coriander",
2,
4,
"A_scene_of_Coriander_leaves.JPG"
)
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val plantAdapter = moshi.adapter(PlantKotlinData::class.java)
logJson<PlantKotlinData>(plant,plantAdapter)
}
5、InputSteam 流的解析
// import okio.buffer
// import okio.source
suspend fun inputStream(context: Context){
coroutineScope {
try {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val inputStream = context.assets.open("plants.json")
val plantListType = Types.newParameterizedType(List::class.java, Plant::class.java)
val plantListAdapter = moshi.adapter<List<Plant>>(plantListType)
val plantList = plantListAdapter.fromJson(inputStream.source().buffer()) ?: emptyList()
logJson<List<Plant>>(plantList,plantListAdapter)
}catch (e:Exception){
log("数据流解析失败")
}
}
}
6、Kotlin OutputSteam
fun <T> outStream(obj: T, context: Context) {
val file = File(context.cacheDir, "textKotlin.txt")
if (!file.exists()) file.createNewFile()
log("${file.absolutePath} : ${file.exists()}")
val fileOutputStream = FileOutputStream(file)
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(obj!!::class.java as Class<T>?) //根据泛型获取adapter
val out = fileOutputStream.sink().buffer() //OutputStream 转化为 Sink.buffer
adapter.toJson(out, obj) //对象数据的写入
out.flush()
log("kotlin end")
}
7、Java OutputSteam
public static <T> void outStream(T obj, Context context) {
try {
File file = new File(context.getCacheDir(),"text.txt");
if(!file.exists()) file.createNewFile();
log(file.getAbsolutePath() +":" +file.exists());
FileOutputStream fileOutputStream = new FileOutputStream(file);
Moshi moshi = new Moshi.Builder().build();
//根据泛型获取adapter
JsonAdapter<T> adapter = moshi.adapter((Class<T>) obj.getClass());
//OutputStream 转化为 Sink.buffer
BufferedSink out = Okio.buffer(Okio.sink(fileOutputStream));
//对象数据的写入
adapter.toJson(out, obj);
out.flush();
log("java end");
}catch (Exception e){
Log.e("moshi", e.toString());
}
}
8、自定义 json Adapter
class CardAdapter {
@ToJson
fun toJson(card: Card) = card.rank + card.suit.toString()
@FromJson
fun fromJson(card: String): Card {
if (card.length != 2) throw JsonDataException("Unknown card: $card")
val rank = card[0]
return when (card[1]) {
'C' -> Card(rank, Suit.CLUBS)
'D' -> Card(rank, Suit.DIAMONDS)
'H' -> Card(rank, Suit.HEARTS)
'S' -> Card(rank, Suit.SPADES)
else -> throw JsonDataException("unknown suit: $card")
}
}
}
fun parserCustom(){
val text = """
{
"hidden_card": "6S",
"visible_cards":[
"4C",
"AH"
]
}
""".trimIndent()
val moshi = Moshi.Builder().add(CardAdapter()).add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter(BlackjackHand::class.java)
val blackjackHand = jsonAdapter.fromJson(text)
log(blackjackHand.toString())
}
9、base64 转换
fun base64Decode() {
val json = "\"TW9zaGksIE9saXZlLCBXaGl0ZSBDaGluPw\""
val moshi = Moshi.Builder().add(ByteString::class.java, Base64ByteStringAdapter()).build()
val jsonAdapter: JsonAdapter<ByteString> = moshi.adapter(ByteString::class.java)
val byteString: ByteString = jsonAdapter.fromJson(json)
log(byteString.toString()) //输出 [text=Moshi, Olive, White Chin?]
}
class Base64ByteStringAdapter : JsonAdapter<ByteString>() {
override fun fromJson(reader: JsonReader): ByteString? {
val base64: String = reader.nextString()
println(base64)
return base64.decodeBase64()
}
override fun toJson(writer: JsonWriter, value: ByteString?) {
val string = value?.base64()
writer.value(string)
}
}
10、自定义 AdapterFactory
fun customAdapterFactory(){
val moshi = Moshi.Builder().add(SortedSetAdapterFactory()).build()
val jsonAdapter: JsonAdapter<SortedSet<String>> = moshi.adapter(
Types.newParameterizedType(
SortedSet::class.java, String::class.java
)
)
val model: TreeSet<String> = TreeSet()
model.add("a")
model.add("b")
model.add("d")
model.add("c")
val json = jsonAdapter.toJson(model)
log(json)
}
class SortedSetAdapter<T>(private val elementAdapter:JsonAdapter<T>): JsonAdapter<SortedSet<T>>() {
override fun fromJson(reader: JsonReader): SortedSet<T> {
val result: TreeSet<T> = TreeSet()
reader.beginArray()
while (reader.hasNext()) {
elementAdapter.fromJson(reader)?.let { result.add(it) }
}
reader.endArray()
return result
}
override fun toJson(writer: JsonWriter, value: SortedSet<T>?) {
writer.beginArray()
if(value != null) {
for (element in value) {
elementAdapter.toJson(writer, element)
}
}
writer.endArray()
}
}
class SortedSetAdapterFactory:JsonAdapter.Factory {
override fun create(
type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi
): JsonAdapter<*>? {
if(annotations.isNotEmpty()) return null
if(type !is ParameterizedType)return null
if(type.rawType != SortedSet::class.java) return null
val elementType = type.actualTypeArguments[0]
val elementAdapter:JsonAdapter<Any?> = moshi.adapter(elementType)
return SortedSetAdapter(elementAdapter).nullSafe()
}
}
11、自定义代理 Delegate
fun customAdapterWithDelegate() {
val data = """
[
{
"name":"not-started"
},
{
"name":"in-progress"
},
{
"name":"in-progress2"
},
{
"name":"rejected"
},
{
"name":"completed"
}
]
""".trimIndent()
val moshi = Moshi.Builder().add(StageAdapter()).add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter<List<StageEle>>(
Types.newParameterizedType(
List::class.java,
StageEle::class.java
)
)
log(jsonAdapter.fromJson(data).toString())
}
class StageAdapter {
@FromJson
fun fromJson(jsonReader: JsonReader, delegate: JsonAdapter<Stage>): Stage {
val value = jsonReader.nextString()
return if (value.startsWith("in-progress")) {
Stage.IN_PROGRESS
} else {
delegate.fromJsonValue(value) ?: Stage.IN_PROGRESS
}
}
}
enum class Stage {
@Json(name = "not-started") NOT_STARTED, @Json(name = "in-progress") IN_PROGRESS,
@Json(name = "rejected") REJECTED, @Json(name = "completed") COMPLETED
}
data class StageEle(val name: Stage)
12、JsonQualifier 颜色转换
class ColorAdapter {
@ToJson
fun toJson(@HexColor rgb: Int): String = String.format("#%06x", rgb)
@FromJson
@HexColor
fun fromJson(rgb: String): Int = Integer.parseInt(rgb.substring(1), 16)
}
@Retention(AnnotationRetention.RUNTIME) @JsonQualifier annotation class HexColor
internal class Rectangle {
private var hidth = 0
private val height = 0
@HexColor var color = 0override fun toString(): String {
return String.format("%dx%d #%06x ->%d", width, height, color, color)
}
}
fun customQualifier() {
val data = """
{
"color":"#ff0000",
"height":768,
"width":1024
}
""".trimIndent()
val moshi = Moshi.Builder().add(ColorAdapter()).add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter(
Rectangle::class.java
)
val rectangle: Rectangle = jsonAdapter.fromJson(data)
log(rectangle.toString())
}
12、跳过错误值,并把错误值设置为默认值
class DefaultOnDataMismatchAdapter<T> private constructor(private val delegate: JsonAdapter<T>, private val defaultValue: T) :
JsonAdapter<T>() {
override fun fromJson(reader: JsonReader): T? {
val peeked = reader.peekJson()
return try {
delegate.fromJson(peeked)
} catch (e: Exception) {
defaultValue
} finally {
peeked.close()
// Skip the value back on the reader, no matter the state of the peeked reader.
reader.skipValue()
}
}
override fun toJson(writer: JsonWriter, value: T?) {
delegate.toJson(writer, value)
}
companion object{
fun <T>newFactory(type:Class<T>,defaultValue: T): Factory =object :Factory{
override fun create(
requestedType: Type, annotations: MutableSet<out Annotation>, moshi: Moshi
): JsonAdapter<T>? {
if (type != requestedType) return null
val delegate: JsonAdapter<T> = moshi.nextAdapter(this, type, annotations)
return DefaultOnDataMismatchAdapter(delegate, defaultValue)
}
}
}
}
fun recoverFromTypeMismatch() {
// 只接收 CLUBS(梅花) ,DIAMONDS(方块),HEARTS(红桃), SPADES(黑桃) 所以 STARS 自动转化为 Suit.CLUBS
val json = """
["DIAMONDS", "STARS", "HEARTS"]
""".trimIndent()
val moshi =
Moshi.Builder().add(newFactory(Suit::class.java, Suit.CLUBS))
.build()
val jsonAdapter: JsonAdapter<List<Suit>> = moshi.adapter(
Types.newParameterizedType(
MutableList::class.java, Suit::class.java
)
)
log(jsonAdapter.fromJson(json).toString())
}