1
+ package view
2
+
3
+ import androidx.compose.foundation.layout.*
4
+ import androidx.compose.foundation.rememberScrollState
5
+ import androidx.compose.foundation.verticalScroll
6
+ import androidx.compose.material.Button
7
+ import androidx.compose.material.MaterialTheme
8
+ import androidx.compose.material.Text
9
+ import androidx.compose.material.TextField
10
+ import androidx.compose.runtime.*
11
+ import androidx.compose.ui.Modifier
12
+ import androidx.compose.ui.unit.dp
13
+ import globalJson
14
+ import kotlinx.serialization.json.JsonArray
15
+ import kotlinx.serialization.json.JsonObject
16
+
17
+ @Composable
18
+ fun JsonView () {
19
+ var jsonString by remember { mutableStateOf(" " ) }
20
+ var jsonErrorMessage by remember { mutableStateOf<String ?>(null ) }
21
+ var jsonObject by remember { mutableStateOf<JsonObject ?>(null ) }
22
+ val isExpandedAll = mutableStateOf(false )
23
+
24
+
25
+ Column (modifier = Modifier .padding(16 .dp)) {
26
+ Text (" Enter JSON String:" )
27
+ TextField (
28
+ value = jsonString,
29
+ onValueChange = {
30
+ jsonString = it
31
+
32
+ try {
33
+ jsonObject = globalJson.decodeFromString(jsonString)
34
+ jsonErrorMessage = null
35
+ } catch (e: Exception ) {
36
+ jsonObject = null
37
+ jsonErrorMessage = " Invalid JSON format: ${e.localizedMessage} "
38
+ }
39
+ },
40
+ modifier = Modifier .fillMaxWidth().padding(bottom = 8 .dp).height(200 .dp),
41
+ placeholder = { Text (" Enter JSON here..." ) }
42
+ )
43
+
44
+ jsonErrorMessage?.let {
45
+ Text (text = it, color = MaterialTheme .colors.error)
46
+ }
47
+
48
+ Spacer (modifier = Modifier .height(16 .dp))
49
+
50
+ Row (modifier = Modifier .fillMaxWidth(), horizontalArrangement = Arrangement .SpaceBetween ) {
51
+ Button (onClick = { isExpandedAll.value = true }) {
52
+ Text (" Expand All" )
53
+ }
54
+ Button (onClick = { isExpandedAll.value = false }) {
55
+ Text (" Collapse All" )
56
+ }
57
+ }
58
+
59
+ Spacer (modifier = Modifier .height(16 .dp))
60
+
61
+
62
+ jsonObject?.let {
63
+ ExpandableJsonTreeView (json = it, isExpandedAll)
64
+ }
65
+ }
66
+ }
67
+
68
+ @Composable
69
+ fun ExpandableJsonTreeView (json : JsonObject , isExpandedAll : MutableState <Boolean >) {
70
+ val scrollState = rememberScrollState()
71
+ Column (modifier = Modifier .verticalScroll(scrollState)) {
72
+ RenderJsonTree (json, level = 0 , isExpandedAll)
73
+ }
74
+ }
75
+
76
+ @Composable
77
+ fun RenderJsonTree (json : JsonObject , level : Int , isExpandedAll : MutableState <Boolean >) {
78
+ json.keys.forEach {
79
+ JsonTreeItem (it, json[it]!! , level, isExpandedAll)
80
+ }
81
+ }
82
+
83
+ @Composable
84
+ fun JsonTreeItem (key : String , value : Any , level : Int , isExpandedAll : MutableState <Boolean >) {
85
+ var isExpanded by remember { mutableStateOf(isExpandedAll.value)}
86
+ val indentation = " " .repeat(level)
87
+
88
+ Column (modifier = Modifier .padding(start = 16 .dp * level)) {
89
+ if (value is JsonObject || value is JsonArray ) {
90
+ Row {
91
+ Button (onClick = { isExpanded = ! isExpanded }) {
92
+ Text (text = if (isExpanded) " [-]" else " [+]" )
93
+ }
94
+ Text (text = " $indentation$key :" )
95
+ }
96
+
97
+ if (isExpanded) {
98
+ when (value) {
99
+ is JsonObject -> RenderJsonTree (
100
+ value,
101
+ level + 1 ,
102
+ isExpandedAll
103
+ )
104
+ is JsonArray -> RenderJsonArray (value, level + 1 , isExpandedAll)
105
+ }
106
+ }
107
+ } else {
108
+ Row {
109
+ Text (text = " $indentation$key : $value " )
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ @Composable
116
+ fun RenderJsonArray (array : JsonArray , level : Int , isExpandedAll : MutableState <Boolean >) {
117
+ array.forEachIndexed { index, item ->
118
+ val indentation = " " .repeat(level)
119
+ Column (modifier = Modifier .padding(start = 16 .dp * level)) {
120
+ Row {
121
+ Text (text = " $indentation [Index $index ]: " )
122
+ }
123
+
124
+
125
+ when (item) {
126
+ is JsonObject -> RenderJsonTree (item, level + 1 , isExpandedAll)
127
+ is JsonArray -> RenderJsonArray (item, level + 1 , isExpandedAll)
128
+ else -> Row { Text (text = " $indentation$item " ) }
129
+ }
130
+ }
131
+ }
132
+ }
0 commit comments