
Dynamically converts JSON into Jetpack Compose components, enabling server-driven UI, generative UI with AI integration, and facilitating UI updates without app redeployment.
A library that dynamically converts JSON into Jetpack Compose components.
json-to-compose is an Android library that allows you to convert JSON structures into Jetpack Compose components at runtime. This makes it easy to create dynamic interfaces and update UI based on remote data.
This library is perfect for implementing Server-Driven UI patterns, where your backend controls the UI layout and content. Some benefits include:
Example:
@Composable
fun App() {
var uiDefinition by remember { mutableStateOf(api.fetchUIDefinition()) }
LaunchedEffect(Unit) {
uiDefinition = api.fetchUIDefinition()
}
uiDefinition.ToCompose()
}Integrate with AI services to create dynamic UIs based on user input or context:
Example:
@Composable
fun App(userContext: String) {
val aiGeneratedUI = aiService.generateUIForUser(userContext)
aiGeneratedUI.ToCompose()
}Add the following dependency to your build.gradle.kts file:
dependencies {
implementation("com.jesusdmedinac:json-to-compose:1.1.0")
}@Composable
fun App() {
MaterialTheme {
JSON_AS_STRING.ToCompose()
}
}
val JSON_AS_STRING = """
{
"type": "Column",
"properties": {
"type": "ColumnProps",
"children": [
{
"type": "Text",
"properties": {
"type": "TextProps",
"text": "Hello World"
}
}
]
}
}
""".trimIndent()@Composable
fun App() {
val behaviors = mapOf(
"button_clicked" to object : Behavior {
override fun onClick() {
println("Button was clicked!")
}
}
)
CompositionLocalProvider(LocalBehavior provides behaviors) {
MaterialTheme {
JSON_AS_STRING.ToCompose()
}
}
}@Composable
fun App() {
var textValue by remember { mutableStateOf("") }
val stateHosts = mapOf(
"my_text_field" to object : StateHost<String> {
override val state: String get() = textValue
override fun onStateChange(state: String) {
textValue = state
}
}
)
CompositionLocalProvider(LocalStateHost provides stateHosts) {
JSON_AS_STRING.ToCompose()
}
}@Composable
fun App() {
val drawableResources = mapOf(
"my_icon" to Res.drawable.my_icon
)
CompositionLocalProvider(LocalDrawableResources provides drawableResources) {
JSON_AS_STRING.ToCompose()
}
}| Component | Description |
|---|---|
| Text | Display text |
| Button | Clickable button with child content |
| Column | Vertical layout container |
| Row | Horizontal layout container |
| Box | Stacking layout container |
| Image | Display images from URL or local resources |
| TextField | Text input field |
| LazyColumn | Lazy vertical scrolling list |
| LazyRow | Lazy horizontal scrolling list |
| Scaffold | Material Design scaffold layout |
| Card | Material Design card container |
| AlertDialog | Material Design alert dialog |
| TopAppBar | Material Design top app bar |
| Custom | User-defined custom components |
Extend the library with your own components without forking:
// 1. Define your custom renderer
val customRenderers = mapOf(
"ProductCard" to { node: ComposeNode ->
val props = node.properties as? NodeProperties.CustomProps
val data = props?.customData
val title = data?.get("title")?.jsonPrimitive?.content ?: ""
val price = data?.get("price")?.jsonPrimitive?.content ?: ""
Card {
Column {
Text(text = title)
Text(text = "$$price")
}
}
}
)
// 2. Provide it to the composition
CompositionLocalProvider(LocalCustomRenderers provides customRenderers) {
JSON_AS_STRING.ToCompose()
}JSON for custom component:
{
"type": "Custom",
"properties": {
"type": "CustomProps",
"customType": "ProductCard",
"customData": {
"title": "My Product",
"price": "99.99"
}
}
}Apply modifiers to any component using composeModifier:
{
"type": "Box",
"properties": { "type": "BoxProps" },
"composeModifier": {
"operations": [
{ "type": "FillMaxWidth" },
{ "type": "Height", "value": 200 },
{ "type": "Padding", "value": 16 },
{ "type": "BackgroundColor", "color": "#FF5722" }
]
}
}Available operations:
Padding - Add padding (value in dp)FillMaxSize - Fill maximum available sizeFillMaxWidth - Fill maximum widthFillMaxHeight - Fill maximum heightWidth - Set specific width (value in dp)Height - Set specific height (value in dp)BackgroundColor - Set background color (hex color){
"type": "Box",
"properties": {
"type": "BoxProps",
"contentAlignment": "Center"
}
}Values: TopStart, TopCenter, TopEnd, CenterStart, Center, CenterEnd, BottomStart, BottomCenter, BottomEnd
{
"type": "Column",
"properties": {
"type": "ColumnProps",
"verticalArrangement": "SpaceBetween",
"horizontalAlignment": "CenterHorizontally"
}
}Vertical Arrangement: Top, Bottom, Center, SpaceEvenly, SpaceBetween, SpaceAround
Horizontal Alignment: Start, CenterHorizontally, End
{
"type": "Row",
"properties": {
"type": "RowProps",
"horizontalArrangement": "SpaceEvenly",
"verticalAlignment": "CenterVertically"
}
}Horizontal Arrangement: Start, End, Center, SpaceEvenly, SpaceBetween, SpaceAround
Vertical Alignment: Top, CenterVertically, Bottom
Composy is a web and desktop app that facilitates the creation of JSON structures for json-to-compose. It provides a compose-tree editor, real-time preview, and export functionality. Composy is perfect for designing dynamic UIs and generating JSON definitions for your app.
WIP
WIP
This project is licensed under the MIT License - see the LICENSE file for details.
If you have questions or suggestions, feel free to:
A library that dynamically converts JSON into Jetpack Compose components.
json-to-compose is an Android library that allows you to convert JSON structures into Jetpack Compose components at runtime. This makes it easy to create dynamic interfaces and update UI based on remote data.
This library is perfect for implementing Server-Driven UI patterns, where your backend controls the UI layout and content. Some benefits include:
Example:
@Composable
fun App() {
var uiDefinition by remember { mutableStateOf(api.fetchUIDefinition()) }
LaunchedEffect(Unit) {
uiDefinition = api.fetchUIDefinition()
}
uiDefinition.ToCompose()
}Integrate with AI services to create dynamic UIs based on user input or context:
Example:
@Composable
fun App(userContext: String) {
val aiGeneratedUI = aiService.generateUIForUser(userContext)
aiGeneratedUI.ToCompose()
}Add the following dependency to your build.gradle.kts file:
dependencies {
implementation("com.jesusdmedinac:json-to-compose:1.1.0")
}@Composable
fun App() {
MaterialTheme {
JSON_AS_STRING.ToCompose()
}
}
val JSON_AS_STRING = """
{
"type": "Column",
"properties": {
"type": "ColumnProps",
"children": [
{
"type": "Text",
"properties": {
"type": "TextProps",
"text": "Hello World"
}
}
]
}
}
""".trimIndent()@Composable
fun App() {
val behaviors = mapOf(
"button_clicked" to object : Behavior {
override fun onClick() {
println("Button was clicked!")
}
}
)
CompositionLocalProvider(LocalBehavior provides behaviors) {
MaterialTheme {
JSON_AS_STRING.ToCompose()
}
}
}@Composable
fun App() {
var textValue by remember { mutableStateOf("") }
val stateHosts = mapOf(
"my_text_field" to object : StateHost<String> {
override val state: String get() = textValue
override fun onStateChange(state: String) {
textValue = state
}
}
)
CompositionLocalProvider(LocalStateHost provides stateHosts) {
JSON_AS_STRING.ToCompose()
}
}@Composable
fun App() {
val drawableResources = mapOf(
"my_icon" to Res.drawable.my_icon
)
CompositionLocalProvider(LocalDrawableResources provides drawableResources) {
JSON_AS_STRING.ToCompose()
}
}| Component | Description |
|---|---|
| Text | Display text |
| Button | Clickable button with child content |
| Column | Vertical layout container |
| Row | Horizontal layout container |
| Box | Stacking layout container |
| Image | Display images from URL or local resources |
| TextField | Text input field |
| LazyColumn | Lazy vertical scrolling list |
| LazyRow | Lazy horizontal scrolling list |
| Scaffold | Material Design scaffold layout |
| Card | Material Design card container |
| AlertDialog | Material Design alert dialog |
| TopAppBar | Material Design top app bar |
| Custom | User-defined custom components |
Extend the library with your own components without forking:
// 1. Define your custom renderer
val customRenderers = mapOf(
"ProductCard" to { node: ComposeNode ->
val props = node.properties as? NodeProperties.CustomProps
val data = props?.customData
val title = data?.get("title")?.jsonPrimitive?.content ?: ""
val price = data?.get("price")?.jsonPrimitive?.content ?: ""
Card {
Column {
Text(text = title)
Text(text = "$$price")
}
}
}
)
// 2. Provide it to the composition
CompositionLocalProvider(LocalCustomRenderers provides customRenderers) {
JSON_AS_STRING.ToCompose()
}JSON for custom component:
{
"type": "Custom",
"properties": {
"type": "CustomProps",
"customType": "ProductCard",
"customData": {
"title": "My Product",
"price": "99.99"
}
}
}Apply modifiers to any component using composeModifier:
{
"type": "Box",
"properties": { "type": "BoxProps" },
"composeModifier": {
"operations": [
{ "type": "FillMaxWidth" },
{ "type": "Height", "value": 200 },
{ "type": "Padding", "value": 16 },
{ "type": "BackgroundColor", "color": "#FF5722" }
]
}
}Available operations:
Padding - Add padding (value in dp)FillMaxSize - Fill maximum available sizeFillMaxWidth - Fill maximum widthFillMaxHeight - Fill maximum heightWidth - Set specific width (value in dp)Height - Set specific height (value in dp)BackgroundColor - Set background color (hex color){
"type": "Box",
"properties": {
"type": "BoxProps",
"contentAlignment": "Center"
}
}Values: TopStart, TopCenter, TopEnd, CenterStart, Center, CenterEnd, BottomStart, BottomCenter, BottomEnd
{
"type": "Column",
"properties": {
"type": "ColumnProps",
"verticalArrangement": "SpaceBetween",
"horizontalAlignment": "CenterHorizontally"
}
}Vertical Arrangement: Top, Bottom, Center, SpaceEvenly, SpaceBetween, SpaceAround
Horizontal Alignment: Start, CenterHorizontally, End
{
"type": "Row",
"properties": {
"type": "RowProps",
"horizontalArrangement": "SpaceEvenly",
"verticalAlignment": "CenterVertically"
}
}Horizontal Arrangement: Start, End, Center, SpaceEvenly, SpaceBetween, SpaceAround
Vertical Alignment: Top, CenterVertically, Bottom
Composy is a web and desktop app that facilitates the creation of JSON structures for json-to-compose. It provides a compose-tree editor, real-time preview, and export functionality. Composy is perfect for designing dynamic UIs and generating JSON definitions for your app.
WIP
WIP
This project is licensed under the MIT License - see the LICENSE file for details.
If you have questions or suggestions, feel free to: