热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

类似GraphQL,自定义json输出,Kotlin实现

2019独角兽企业重金招聘Python工程师标准第一次见GraphQL的时候是去年,完全被惊呆了,心想这么牛逼,前台想要什么就可以拿

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

第一次见GraphQL的时候是去年,完全被惊呆了,心想这么牛逼,前台想要什么就可以拿到什么数据,不想要的完全可以不获取,之后就开始尝试使用GraphQL,然后发现入门失败。

但是自己又有这方面的需求,比如有一个数据格式(暂定用户信息),有多个接口需要获取它的信息,而且每个接口的需求不一样,也可能后端为了限制某些字段不给某个接口返回。

例如:用户(id,姓名,年龄,爱好,出生日期,身份证,密码,头像)

A接口:只需要(姓名、年龄、爱好),其他信息无权限获取

B接口:需要(姓名、出生日期、身份证、头像),其他信息并不关心,且密码无法获取

C接口:有权限获取全部信息,但又不需要全部信息

当遇到这种情况的时候基础的json可以较方便的解决,但是如果遇到联级的信息呢??

比如:国家(名称,地区(名称,市(名称,县....)))这样联级的信息,就难搞了。

因此需要GraphQL这样的工具,直接写一个字符串去过滤出需要的数据({country{name,Area{name,city{name,county}}}})只通过这个字符串就过滤出我们需要的json数据。

下面进入代码阶段(完整的代码在最后面贴出来)

开发语言:Kotlin

开发平台:Windows

开发工具:Idea

完整代码:https://gitee.com/houkunlin/goour-utils/blob/master/src/main/kotlin/cn/goour/kotlin/tools/MapTools.kt

第一步:写一个字符串解析方法,解析过滤字符串,解析成map键值对形式,key为字段信息,value为子类嵌套过滤字符串

private fun getKeyMap(key: String): HashMap {val keyMap = hashMapOf()var lastIndex = 0var endIndex = 0var left = 0key.forEachIndexed { index, c ->when (c) {',' -> {if (left == 0 && lastIndex {if (left == 0) {endIndex = index}++left}'}' -> {if (--left == 0) {keyMap[key.substring(lastIndex, endIndex).replace(",", "")] = key.substring(endIndex + 1, index)lastIndex = index + 2}}}if (index == key.lastIndex && lastIndex }

第二步:就是开始对bean的字段进行过滤了,返回一个map,key为字段信息,value为字段值

fun Any.toMapInclude(key: String): Map {val keyMap &#61; getKeyMap(key)val fields &#61; this.javaClass.declaredFieldsval map &#61; hashMapOf()fields.forEach {it.isAccessible &#61; trueif (keyMap.contains(it.name) && it.name !&#61; "Companion") {val value &#61; keyMap[it.name]if (value !&#61; null) {val obj &#61; it.get(this)when {Iterable::class.java.isInstance(obj) -> {val list &#61; arrayListOf()obj as Collection<*>obj.forEach {if (it !&#61; null) {list &#43;&#61; it.toMapInclude(value)}}map[it.name] &#61; list}it.type.isArray -> {val list &#61; arrayListOf()obj as Array<*>obj.forEach {if (it !&#61; null) {list &#43;&#61; it.toMapInclude(value)}}map[it.name] &#61; list}else -> map[it.name] &#61; obj.toMapInclude(value)}} else {val obj &#61; it.get(this)when {it.type.isArray -> {obj as Array<*>map[it.name] &#61; obj.toList()}else -> map[it.name] &#61; it.get(this)}}}}return map
}

OK&#xff0c;完工&#xff0c;之后开始测试跑一下


fun main(args: Array) {val g &#61; Country(name &#61; "中国",area &#61; Area(name &#61; "广西", gps &#61; arrayOf("1.x", "2.x"),city &#61; City(name &#61; "桂林",county &#61; listOf(County(name &#61; "测试县城1", gps &#61; arrayOf("1.x", "2.x")),County(name &#61; "测试县城2", gps &#61; arrayOf("11.x", "22.x"))))))val str &#61; "name,area{name,gps,city{name,county{name}}}"println(g.toMapInclude(str))//{area&#61;{city&#61;{name&#61;桂林, county&#61;[{name&#61;测试县城1}, {name&#61;测试县城2}]}, name&#61;广西, gps&#61;[1.x, 2.x]}, name&#61;中国}println(g.toMapInclude(str).toJsonString())//{"area":{"city":{"name":"桂林","county":[{"name":"测试县城1"},{"name":"测试县城2"}]},"name":"广西","gps":["1.x","2.x"]},"name":"中国"}
}

下面贴另一份测试结果

fun main(args: Array) {val g &#61; Country(name &#61; "中国",area &#61; Area(name &#61; "广西", gps &#61; arrayOf("1.x", "2.x"),city &#61; City(name &#61; "桂林",county &#61; listOf(County(name &#61; "测试县城1", gps &#61; arrayOf("1.x", "2.x")),County(name &#61; "测试县城2", gps &#61; arrayOf("11.x", "22.x"))))))val str &#61; "name,area{name,gps,city{name,county{name}}}"println(g.toMapInclude(str))println(g.toMapInclude(str).toJsonString())var start &#61; System.currentTimeMillis()for (i in 1..100000) {g.toMap()}var end &#61; System.currentTimeMillis()println("转map耗时&#xff1a;${(end - start) / 1000.0}s")start &#61; System.currentTimeMillis()for (i in 1..100000) {g.toMapInclude(str)}end &#61; System.currentTimeMillis()println("过滤耗时&#xff1a;${(end - start) / 1000.0}s")start &#61; System.currentTimeMillis()for (i in 1..100000) {JSONObject.toJSON(g)}end &#61; System.currentTimeMillis()println("json耗时&#xff1a;${(end - start) / 1000.0}s")start &#61; System.currentTimeMillis()for (i in 1..100000) {g.toMapInclude(str).toJsonString()}end &#61; System.currentTimeMillis()println("转map转json耗时&#xff1a;${(end - start) / 1000.0}s")
}
/*
运行结果
电脑处理器&#xff1a;AMD A12-9700P 2.50GHz
内存RAM&#xff1a;8.00GB&#xff08;7.46GB可用&#xff09;
{area&#61;{city&#61;{name&#61;桂林, county&#61;[{name&#61;测试县城1}, {name&#61;测试县城2}]}, name&#61;广西, gps&#61;[1.x, 2.x]}, name&#61;中国}
{"area":{"city":{"name":"桂林","county":[{"name":"测试县城1"},{"name":"测试县城2"}]},"name":"广西","gps":["1.x","2.x"]},"name":"中国"}
转map耗时&#xff1a;0.097s
过滤耗时&#xff1a;1.213s
json耗时&#xff1a;1.092s
转map转json耗时&#xff1a;2.074s
*/

下面贴全部完整的代码

package cn.goour.kotlin.toolsimport com.alibaba.fastjson.JSONObjectfun Any.toMap(): Map {val fields &#61; this.javaClass.declaredFieldsval map &#61; hashMapOf()fields.forEach {it.isAccessible &#61; trueif (it.name !&#61; "Companion") {map[it.name] &#61; it.get(this)}
// println(it.name &#43; " " &#43; it.type.name &#43; " " &#43; it.get(this))}return map
}private fun getKeyMap(key: String): HashMap {
// println(key)val keyMap &#61; hashMapOf()var lastIndex &#61; 0var endIndex &#61; 0var left &#61; 0key.forEachIndexed { index, c ->// println("$index &#61; $c")when (c) {&#39;,&#39; -> {if (left &#61;&#61; 0 && lastIndex // println("$lastIndex -- $endIndex")
// println("${key.substring(lastIndex, endIndex)} -- null")keyMap[key.substring(lastIndex, endIndex).replace(",", "")] &#61; nulllastIndex &#61; index &#43; 1}}&#39;{&#39; -> {if (left &#61;&#61; 0) {endIndex &#61; index}&#43;&#43;left}&#39;}&#39; -> {if (--left &#61;&#61; 0) {
// println("$lastIndex -- $endIndex -- $index")
// println("${key.substring(lastIndex, endIndex)} -- ${key.substring(endIndex &#43; 1, index)}")keyMap[key.substring(lastIndex, endIndex).replace(",", "")] &#61; key.substring(endIndex &#43; 1, index)lastIndex &#61; index &#43; 2}}}if (index &#61;&#61; key.lastIndex && lastIndex // println("$lastIndex -- $endIndex")
// println("${key.substring(lastIndex)} -- null")keyMap[key.substring(lastIndex).replace(",", "")] &#61; null}}return keyMap
}fun Any.toMapInclude(key: String): Map {
// println(key)val keyMap &#61; getKeyMap(key)val fields &#61; this.javaClass.declaredFieldsval map &#61; hashMapOf()fields.forEach {it.isAccessible &#61; trueif (keyMap.contains(it.name) && it.name !&#61; "Companion") {val value &#61; keyMap[it.name]if (value !&#61; null) {val obj &#61; it.get(this)when {Iterable::class.java.isInstance(obj) -> {val list &#61; arrayListOf()obj as Collection<*>obj.forEach {if (it !&#61; null) {list &#43;&#61; it.toMapInclude(value)}}map[it.name] &#61; list}it.type.isArray -> {val list &#61; arrayListOf()obj as Array<*>obj.forEach {if (it !&#61; null) {list &#43;&#61; it.toMapInclude(value)}}map[it.name] &#61; list}else -> map[it.name] &#61; obj.toMapInclude(value)}} else {val obj &#61; it.get(this)when {it.type.isArray -> {obj as Array<*>map[it.name] &#61; obj.toList()}else -> map[it.name] &#61; it.get(this)}}}}return map
}fun Map<*, *>.toJsonString(dateFormat: String &#61; "yyyy-MM-dd HH:mm:ss"): String {return JSONObject.toJSONStringWithDateFormat(this, dateFormat)
}fun main(args: Array) {val g &#61; Country(name &#61; "中国",area &#61; Area(name &#61; "广西", gps &#61; arrayOf("1.x", "2.x"),city &#61; City(name &#61; "桂林",county &#61; listOf(County(name &#61; "测试县城1", gps &#61; arrayOf("1.x", "2.x")),County(name &#61; "测试县城2", gps &#61; arrayOf("11.x", "22.x"))))))val str &#61; "name,area{name,gps,city{name,county{name}}}"println(g.toMapInclude(str))println(g.toMapInclude(str).toJsonString())var start &#61; System.currentTimeMillis()for (i in 1..100000) {g.toMap()}var end &#61; System.currentTimeMillis()println("转map耗时&#xff1a;${(end - start) / 1000.0}s")start &#61; System.currentTimeMillis()for (i in 1..100000) {g.toMapInclude(str)}end &#61; System.currentTimeMillis()println("过滤耗时&#xff1a;${(end - start) / 1000.0}s")start &#61; System.currentTimeMillis()for (i in 1..100000) {JSONObject.toJSON(g)}end &#61; System.currentTimeMillis()println("json耗时&#xff1a;${(end - start) / 1000.0}s")start &#61; System.currentTimeMillis()for (i in 1..100000) {g.toMapInclude(str).toJsonString()}end &#61; System.currentTimeMillis()println("转map转json耗时&#xff1a;${(end - start) / 1000.0}s")
}data class Country(var name: String,var area: Area? &#61; null
)data class Area(var name: String,var gps: Array? &#61; null,var city: City? &#61; null
)data class City(var name: String,var county: List
)data class County(var name: String,var gps: Array? &#61; null
)

 


转:https://my.oschina.net/houkunlin/blog/1618145



推荐阅读
author-avatar
柳绿海蓝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有