mirror of
https://github.com/foss42/apidash.git
synced 2025-12-03 19:39:25 +08:00
307 lines
8.4 KiB
Markdown
307 lines
8.4 KiB
Markdown
# JSON Explorer
|
|
|
|
[](https://pub.dev/packages/json_explorer)
|
|
|
|
A Flutter widget to render, view and interact with JSON. It also includes interactive search/find capabilities.
|
|
|
|
Maintained fork of [json_data_explorer](https://pub.dev/packages/json_data_explorer) with bug fixes & improvements.
|
|
|
|
| Interact with JSON | Search capabilities |
|
|
| --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
|  |  |
|
|
|
|
## Features
|
|
|
|
- Expand and collapse classes and array nodes.
|
|
- Dynamic search with highlight.
|
|
- Configurable theme and interactions.
|
|
- Configurable data display format.
|
|
- Indentation guidelines.
|
|
|
|
## Usage
|
|
|
|
The data to be displayed is managed by a store, the `JsonExplorerStore`.
|
|
In order to use all features from this package you need to register it in
|
|
a [Provider](https://pub.dev/packages/provider).
|
|
|
|
```dart
|
|
final JsonExplorerStore store = JsonExplorerStore();
|
|
|
|
/// ...
|
|
ChangeNotifierProvider.value(
|
|
value: store,
|
|
child:
|
|
/// ...
|
|
```
|
|
|
|
To load a json object, use `JsonExplorerStore.build` nodes method.
|
|
|
|
```dart
|
|
store.buildNodes(json.decode(myJson));
|
|
```
|
|
|
|
To display the data explorer, you can use the `JsonExplorer` widget.
|
|
The only required parameter is a list of node models, which you can take
|
|
from the `JsonExplorerStore` after a json was decoded.
|
|
|
|
```dart
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(widget.title),
|
|
),
|
|
body: SafeArea(
|
|
minimum: const EdgeInsets.all(16),
|
|
child: ChangeNotifierProvider.value(
|
|
value: store,
|
|
child: Consumer<JsonExplorerStore>(
|
|
builder: (context, state, child) => JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
```
|
|
|
|
This will display a decoded json using a default theme.
|
|
|
|
Check the `/example` app for more information on how to customize the
|
|
look and feel of `JsonExplorer` widget.
|
|
|
|
### Changing the look and feel
|
|
|
|
The `JsonExplorer` can be customized to fit different visual requirements.
|
|
|
|
#### Themes:
|
|
|
|
To change fonts and colors, use a `JsonExplorerTheme`:
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
theme: JsonExplorerTheme(
|
|
rootKeyTextStyle: GoogleFonts.inconsolata(
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
propertyKeyTextStyle: GoogleFonts.inconsolata(
|
|
color: Colors.grey,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
keySearchHighlightTextStyle: GoogleFonts.inconsolata(
|
|
color: Colors.black,
|
|
backgroundColor: const Color(0xFFFFEDAD),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
focusedKeySearchHighlightTextStyle:
|
|
GoogleFonts.inconsolata(
|
|
color: Colors.black,
|
|
backgroundColor: const Color(0xFFF29D0B),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
valueTextStyle: GoogleFonts.inconsolata(
|
|
color: const Color(0xFFCA442C),
|
|
fontSize: 16,
|
|
),
|
|
valueSearchHighlightTextStyle: GoogleFonts.inconsolata(
|
|
color: const Color(0xFFCA442C),
|
|
backgroundColor: const Color(0xFFFFEDAD),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
focusedValueSearchHighlightTextStyle:
|
|
GoogleFonts.inconsolata(
|
|
color: Colors.black,
|
|
backgroundColor: const Color(0xFFF29D0B),
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
indentationLineColor: const Color(0xFFE1E1E1),
|
|
highlightColor: const Color(0xFFF1F1F1),
|
|
),
|
|
)
|
|
```
|
|
|
|
#### Formatter:
|
|
|
|
Changing the theme is not the only way to customize how the widget looks,
|
|
`Formatter` methods can be used to change how key and values are converted
|
|
into strings.
|
|
|
|
The default behavior to display json property names is `key:`, but this
|
|
can be changed with a formatter:
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
propertyNameFormatter: (name) => '$name ->',
|
|
)
|
|
```
|
|
|
|
Now all property keys are displayed as `key ->`.
|
|
|
|
#### Changing property style based on value:
|
|
|
|
Property values `style` and `onTap` can be changed dynamically by using
|
|
the `valueStyleBuilder` parameter. It expects a function that receives
|
|
the property `dynamic value` and the current `style`, and returns
|
|
a `PropertyOverrides`.
|
|
|
|
An example is adding interaction to values that contains links:
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
valueStyleBuilder: (value, style) {
|
|
final isUrl = _valueIsUrl(value);
|
|
return PropertyOverrides(
|
|
style: isUrl
|
|
? style.copyWith(
|
|
decoration: TextDecoration.underline,
|
|
)
|
|
: style,
|
|
onTap: isUrl ? () => _launchUrl(value) : null,
|
|
);
|
|
},
|
|
)
|
|
```
|
|
|
|
Or, folowing the same principle, change how the value looks for specific
|
|
value types:
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
valueStyleBuilder: (value, style) {
|
|
if (value is num) {
|
|
return PropertyOverrides(
|
|
style: style.copyWith(
|
|
color: Colors.blue,
|
|
),
|
|
);
|
|
}
|
|
return PropertyOverrides(
|
|
style: style,
|
|
);
|
|
},
|
|
)
|
|
```
|
|
|
|
#### Custom widget components:
|
|
|
|
`collapsableToggleBuilder` allow the expand and collapse button that
|
|
is displayed on root nodes to be changed.
|
|
For example to use a simple implicitly animated widget:
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
collapsableToggleBuilder: (context, node) =>
|
|
AnimatedRotation(
|
|
turns: node.isCollapsed ? -0.25 : 0,
|
|
duration: const Duration(milliseconds: 300),
|
|
child: const Icon(Icons.arrow_drop_down),
|
|
),
|
|
)
|
|
```
|
|
|
|
`rootInformationBuilder` builds a widget that is displayed in classes and
|
|
arrays root nodes.
|
|
As an example, this can be used to display some information about its
|
|
children nodes.
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
rootInformationBuilder: (context, node) => Text(
|
|
node.isClass
|
|
? '{${(node.childrenCount)}}'
|
|
: '[${node.childrenCount}]',
|
|
),
|
|
)
|
|
```
|
|
|
|
`trailingBuilder` builds a trailing widget in each node. The `NodeViewModelState`
|
|
argument allows the widget to react to certain nodes properties.
|
|
To build a widget that appears only when a node is currently focused
|
|
for example:
|
|
|
|
```dart
|
|
JsonExplorer(
|
|
nodes: state.displayNodes,
|
|
trailingBuilder: (context, node) => node.isFocused
|
|
? Text("I'm focused :)")
|
|
: const SizedBox(),
|
|
)
|
|
```
|
|
|
|
### Search
|
|
|
|
`JsonExplorerStore` provides search functionality using the `search` method.
|
|
`JsonExplorer` widget already reacts to those state changes and highlights the search results.
|
|
Refer to `JsonExplorerTheme` to change the looks of search the results.
|
|
|
|
The focused result can be changed by calling the `focusPreviousSearchResult` and `focusNextSearchResult` methods.
|
|
|
|
Here is an example of a simple search bar, you can check a full example
|
|
in the `example` folder.
|
|
|
|
```dart
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: TextField(
|
|
controller: searchController,
|
|
onChanged: (term) => jsonExplorerStore.search(term),
|
|
maxLines: 1,
|
|
decoration: const InputDecoration(
|
|
hintText: 'Search',
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
IconButton(
|
|
onPressed: jsonExplorerStore.focusPreviousSearchResult,
|
|
icon: const Icon(Icons.arrow_drop_up),
|
|
),
|
|
IconButton(
|
|
onPressed: jsonExplorerStore.focusNextSearchResult,
|
|
icon: const Icon(Icons.arrow_drop_down),
|
|
),
|
|
],
|
|
),
|
|
```
|
|
|
|
### Custom scroll widget
|
|
|
|
It is possible to implement your own scrolling by using the `JsonAttribute`
|
|
widget to display each node.
|
|
|
|
A simple `ListView.builder` looks like this:
|
|
|
|
```dart
|
|
ListView.builder(
|
|
itemCount: state.displayNodes.length,
|
|
itemBuilder: (context, index) => JsonAttribute(
|
|
node: state.displayNodes.elementAt(index),
|
|
theme: JsonExplorerTheme.defaultTheme,
|
|
),
|
|
),
|
|
```
|
|
|
|
## Maintainer
|
|
|
|
- Ashita Prasad ([GitHub](https://github.com/ashitaprasad), [LinkedIn](https://www.linkedin.com/in/ashitaprasad/), [X](https://x.com/ashitaprasad))
|
|
|
|
## License
|
|
|
|
This project is licensed under the [BSD 3-Clause License](https://github.com/foss42/apidash/blob/main/packages/json_explorer/LICENSE).
|