PHPackages                             provydon/json-to-keyvalue - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. provydon/json-to-keyvalue

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

provydon/json-to-keyvalue
=========================

A Laravel Nova helper that converts JSON/arrays into read-only KeyValue fields.

v1.1.0(7mo ago)32.9k—8.8%MITPHPPHP &gt;=8.1

Since Oct 9Pushed 6mo agoCompare

[ Source](https://github.com/provydon/json-to-keyvalue)[ Packagist](https://packagist.org/packages/provydon/json-to-keyvalue)[ RSS](/packages/provydon-json-to-keyvalue/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (2)Versions (4)Used By (0)

JSON to KeyValue for Laravel Nova
=================================

[](#json-to-keyvalue-for-laravel-nova)

A Laravel package that transforms nested JSON/arrays into flat, readable key-value pairs for display in Nova's KeyValue field.

[![Buy me a coffee](https://camo.githubusercontent.com/b356092b325a08a855f69a43f8dc67331b51f774a051cc2501a2491701d800d8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4275792532306d6525323061253230636f666665652d2545322539382539352d79656c6c6f772e737667)](https://buymeacoffee.com/provydon)

Why You Need This
-----------------

[](#why-you-need-this)

### The Problem

[](#the-problem)

Not everyone understands JSON — especially regular admin users in your Nova Admin Panel. Nova's built-in KeyValue field doesn't work with nested objects or JSON arrays; it simply displays them as raw JSON strings with index numbers as keys, or sometimes doesn’t display them at all.

**Without this package:**

[![Before - Raw JSON](https://github.com/provydon/json-to-keyvalue/raw/main/screenshots/before.jpg)](https://github.com/provydon/json-to-keyvalue/blob/main/screenshots/before.jpg)[![Before - Nova KeyValue](https://github.com/provydon/json-to-keyvalue/raw/main/screenshots/before2.jpg)](https://github.com/provydon/json-to-keyvalue/blob/main/screenshots/before2.jpg)

### The Solution

[](#the-solution)

This package transforms your JSON data into flat, readable key-value pairs before displaying them using Laravel Nova's existing KeyValue fields.

**With this package:**

[![After - KeyValue Display](https://github.com/provydon/json-to-keyvalue/raw/main/screenshots/after.jpg)](https://github.com/provydon/json-to-keyvalue/blob/main/screenshots/after.jpg)

Features
--------

[](#features)

- 🔄 Handles JSON strings or arrays
- 🔍 Intelligently handles database relationships, resolving foreign keys by fetching and displaying the related record's name or any column you specify.
- 🎯 Automatically flattens nested objects
- 🎨 Pretty key formatting (snake\_case → Title Case)
- 🚫 Smart filtering (exclude by prefix/suffix)
- 📊 Multiple items displayed as separate fields
- ✨ Custom formatters for any field
- 🔒 Read-only, detail-only display
- 🎨 Fluent API for clean, readable code
- 🧰 Built-in formatters (currency, dates, phone, etc.)
- ⚙️ Publishable config for global defaults
- 🎭 Blade component for non-Nova use
- 🎁 Auto-flatten single-item arrays (no more "#1" suffixes!)
- 🔢 Customizable or skippable array indices
- 📦 Conditional flattening based on array size
- 🗂️ Simplified nested array iteration

What's New in v1.1.0
--------------------

[](#whats-new-in-v110)

### Auto-Flatten Single-Item Arrays

[](#auto-flatten-single-item-arrays)

No more seeing "Item #1" when you only have one item! Use `flattenSingleArrays()` to automatically extract single items:

```
JsonToKeyvalue::make($data, 'User')
    ->flattenSingleArrays(true)
    ->toFields();
```

### Simplified Nested Array Iteration

[](#simplified-nested-array-iteration)

Transform complex nested structures with one simple method:

```
// Before
collect($this->data)->flatMap(function ($value, $key) {
    $label = ucwords(str_replace('_', ' ', $key));
    $data = is_array($value) && isset($value[0]) ? $value[0] : $value;
    return JsonToKeyvalue::make($data, $label)->flattenNested(true)->toFields();
})->toArray()

// After
JsonToKeyvalue::fromNestedArray($this->data)
```

### Customizable Array Indices

[](#customizable-array-indices)

Skip indices entirely or customize their format:

```
// Skip completely
->skipArrayIndices(true)

// Use parentheses
->arrayIndexFormat(' (%d)')

// Use brackets
->arrayIndexFormat(' [%d]')
```

### More Control

[](#more-control)

Conditionally flatten arrays and control when to process large datasets:

```
->maxArraySize(10)  // Only process arrays with ≤10 items
```

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel Nova (not included - must be installed separately)

Installation
------------

[](#installation)

```
composer require provydon/json-to-keyvalue
```

Usage
-----

[](#usage)

### Quick Start

[](#quick-start)

The simplest usage:

```
use Provydon\JsonToKeyvalue\JsonToKeyvalue;

public function fields(Request $request)
{
    return [
        JsonToKeyvalue::make($this->metadata, 'Metadata')
            ->toFields()
    ];
}
```

That's it! Your nested JSON is now flattened and displayed as readable key-value pairs.

### Adding Options

[](#adding-options)

You can chain methods to customize the output:

```
use Provydon\JsonToKeyvalue\JsonToKeyvalue;

public function fields(Request $request)
{
    return JsonToKeyvalue::make($this->metadata, 'Metadata')
        ->skip(['password'])
        ->excludeSuffixes(['_error'])
        ->formatters([
            'amount' => fn($value) => '₦' . number_format($value, 2)
        ])
        ->toFields();
}
```

**Why use the class?**

- ✨ Clean, readable, chainable methods
- 🎯 Type hints and IDE autocomplete
- 🔧 Easier to test and maintain
- 📦 Can use `toArray()` for non-Nova contexts

### Helper Function (Legacy)

[](#helper-function-legacy)

The global helper function is still available but less recommended:

```
public function fields(Request $request)
{
    return [
        json_to_keyvalue_fields($this->metadata, 'Metadata', [
            'skip' => ['password'],
            'exclude_suffixes' => ['_error']
        ])
    ];
}
```

### Blade Component (Non-Nova)

[](#blade-component-non-nova)

For displaying key-value pairs outside of Nova:

```

```

API Methods
-----------

[](#api-methods)

### Available Methods

[](#available-methods)

MethodParametersDescription`make($data, $label)`data, labelCreate new instance`fromNestedArray($data, $formatter)`array, ?callableStatic method to iterate nested arrays`skip($keys)`arraySkip specific keys`excludeSuffixes($suffixes)`arrayExclude keys by suffix`excludePrefixes($prefixes)`arrayExclude keys by prefix`flattenNested($bool)`booleanEnable/disable flattening`nestedSeparator($sep)`stringSet separator for nested keys`flattenSingleArrays($bool)`booleanAuto-extract single-item arrays`skipArrayIndices($bool)`booleanSkip adding array indices to labels`arrayIndexFormat($format)`stringCustomize array index format (sprintf)`maxArraySize($size)`?intOnly flatten arrays below this size`itemLabel($label)`stringLabel for array items`labels($labels)`arrayCustom field labels`formatters($formatters)`arrayCustom formatters`lookups($lookups)`arrayDatabase lookups`config($config)`arrayMerge config array`toFields()`-Return Nova fields`toArray()`-Return plain arrays### Examples

[](#examples)

**Skip specific keys**

```
JsonToKeyvalue::make($data, 'Payment Info')
    ->skip(['cvv', 'password', 'secret_key'])
    ->toFields();
```

**Exclude by suffix/prefix**

```
JsonToKeyvalue::make($data, 'Response')
    ->excludeSuffixes(['_error', '_debug', '_internal'])
    ->excludePrefixes(['temp_', 'cache_'])
    ->toFields();
```

**Custom labels**

```
JsonToKeyvalue::make($data, 'User')
    ->labels([
        'dob' => 'Date of Birth',
        'phone_number' => 'Phone',
        'created_at' => 'Member Since'
    ])
    ->toFields();
```

**Custom formatters**

```
JsonToKeyvalue::make($data, 'Transaction')
    ->formatters([
        'amount' => fn($value) => '₦' . number_format($value, 2),
        'created_at' => fn($value) => \Carbon\Carbon::parse($value)->format('M d, Y'),
        'status' => fn($value) => strtoupper($value)
    ])
    ->toFields();
```

**Database lookups**

```
JsonToKeyvalue::make($data, 'Order')
    ->lookups([
        'user_id' => [
            'model' => \App\Models\User::class,
            'field' => 'id',
            'display' => 'name',
            'fallback' => 'user_id'
        ],
        'product_id' => [
            'model' => \App\Models\Product::class,
            'field' => 'id',
            'display' => 'title'
        ]
    ])
    ->toFields();
```

**Nested array handling**

```
JsonToKeyvalue::make($data, 'Config')
    ->flattenNested(true)
    ->nestedSeparator(' > ')
    ->toFields();
```

**Multiple items**

```
$orders = [
    ['id' => 1, 'total' => 5000],
    ['id' => 2, 'total' => 3000]
];

JsonToKeyvalue::make($orders, 'Order')
    ->itemLabel('Order')
    ->toFields();
```

**Auto-flatten single-item arrays**

```
// If your data has single-item arrays like [['name' => 'John']]
// This will extract the item without showing "Item #1"
JsonToKeyvalue::make($data, 'User')
    ->flattenSingleArrays(true)
    ->toFields();
```

**Skip array indices**

```
// Removes "#1", "#2" suffixes from labels
JsonToKeyvalue::make($items, 'Items')
    ->skipArrayIndices(true)
    ->toFields();
```

**Custom array index format**

```
// Customize how array indices are displayed
JsonToKeyvalue::make($items, 'Item')
    ->arrayIndexFormat(' (%d)')  // Item (1), Item (2)
    ->toFields();

// Or use brackets
JsonToKeyvalue::make($items, 'Item')
    ->arrayIndexFormat(' [%d]')  // Item [1], Item [2]
    ->toFields();
```

**Conditional flattening by size**

```
// Only process arrays with 10 or fewer items
JsonToKeyvalue::make($data, 'Large Dataset')
    ->maxArraySize(10)
    ->toFields();
```

**Nested array iteration**

```
// The old way
Panel::make('Details', $this->data
    ? collect($this->data)->flatMap(function ($value, $key) {
        $label = ucwords(str_replace('_', ' ', $key));
        $data = is_array($value) && isset($value[0]) ? $value[0] : $value;
        return JsonToKeyvalue::make($data, $label)->flattenNested(true)->toFields();
    })->toArray()
    : []
),

// The new way ✨
Panel::make('Details',
    $this->data ? JsonToKeyvalue::fromNestedArray($this->data) : []
),

// With custom label formatter
Panel::make('Details',
    $this->data
        ? JsonToKeyvalue::fromNestedArray($this->data, fn($key) => strtoupper($key))
        : []
),
```

**Complete example**

```
use Provydon\JsonToKeyvalue\JsonToKeyvalue;
use Provydon\JsonToKeyvalue\Formatters;

JsonToKeyvalue::make($data, 'Payment Details')
    ->skip(['cvv', 'secret_key'])
    ->excludeSuffixes(['_error', '_debug'])
    ->flattenNested(true)
    ->nestedSeparator(' → ')
    ->labels([
        'transaction_ref' => 'Reference',
        'created_at' => 'Date'
    ])
    ->formatters([
        'amount' => Formatters::currency('₦', 2),
        'created_at' => Formatters::datetime('M d, Y g:i A')
    ])
    ->lookups([
        'user_id' => [
            'model' => \App\Models\User::class,
            'field' => 'id',
            'display' => 'email',
            'fallback' => 'user_id'
        ]
    ])
    ->toFields();
```

**Using `toArray()` for non-Nova contexts**

```
$data = JsonToKeyvalue::make($payment, 'Payment')
    ->skip(['internal_id'])
    ->formatters(['amount' => Formatters::currency('$')])
    ->toArray();
```

Built-in Formatters
-------------------

[](#built-in-formatters)

The package includes ready-to-use formatters:

```
use Provydon\JsonToKeyvalue\JsonToKeyvalue;
use Provydon\JsonToKeyvalue\Formatters;

JsonToKeyvalue::make($data, 'Transaction')
    ->formatters([
        'amount' => Formatters::currency('₦', 2),
        'created_at' => Formatters::date('M d, Y'),
        'updated_at' => Formatters::datetime('M d, Y g:i A'),
        'is_active' => Formatters::boolean('Active', 'Inactive'),
        'status' => Formatters::uppercase(),
        'name' => Formatters::titleCase(),
        'phone' => Formatters::phone('+234'),
        'description' => Formatters::truncate(100),
        'discount' => Formatters::percentage(2),
        'file_size' => Formatters::fileSize(),
        'metadata' => Formatters::json(pretty: true),
        'type' => Formatters::enumLabel([
            'pending' => 'Pending Payment',
            'completed' => 'Completed'
        ])
    ])
    ->toFields();
```

### Available Formatters

[](#available-formatters)

- `currency($symbol, $decimals)` - Format numbers as currency
- `date($format)` - Format dates
- `datetime($format)` - Format date and time
- `boolean($trueLabel, $falseLabel)` - Convert boolean to text
- `uppercase()` - Convert to uppercase
- `lowercase()` - Convert to lowercase
- `titleCase()` - Convert to title case
- `phone($countryCode)` - Format phone numbers
- `truncate($length, $ending)` - Truncate long text
- `percentage($decimals)` - Format as percentage
- `fileSize()` - Convert bytes to human-readable size
- `json($pretty)` - Format as JSON
- `enumLabel($labels)` - Map enum values to labels

Global Configuration
--------------------

[](#global-configuration)

Publish the config file:

```
php artisan vendor:publish --tag=json-to-keyvalue-config
```

Set global defaults in `config/json-to-keyvalue.php`:

```
return [
    'exclude_suffixes' => ['_error', '_debug'],
    'exclude_prefixes' => ['temp_'],
    'flatten_nested' => true,
    'nested_separator' => ' → ',
    'flatten_single_arrays' => false,
    'skip_array_indices' => false,
    'array_index_format' => ' #%d',
    'max_array_size' => null,
    'skip' => [],
    'labels' => [],
    'formatters' => [],
    'lookups' => [],
];
```

Blade Component
---------------

[](#blade-component)

Publish the views:

```
php artisan vendor:publish --tag=json-to-keyvalue-views
```

Use in Blade templates:

```

```

Advanced Usage
--------------

[](#advanced-usage)

### Chaining Multiple Configurations

[](#chaining-multiple-configurations)

```
use Provydon\JsonToKeyvalue\JsonToKeyvalue;
use Provydon\JsonToKeyvalue\Formatters;

JsonToKeyvalue::make($metadata, 'User Metadata')
    ->skip(['password', 'token', 'api_key'])
    ->excludeSuffixes(['_error', '_internal', '_debug'])
    ->excludePrefixes(['temp_', 'cache_'])
    ->flattenNested(true)
    ->nestedSeparator(' → ')
    ->itemLabel('Metadata')
    ->labels([
        'first_name' => 'First Name',
        'last_name' => 'Last Name'
    ])
    ->formatters([
        'created_at' => Formatters::datetime(),
        'amount' => Formatters::currency('₦'),
        'is_active' => Formatters::boolean()
    ])
    ->toFields();
```

### Using Config Array

[](#using-config-array)

For complex configurations, you can pass an array:

```
JsonToKeyvalue::make($data, 'Details')
    ->config([
        'skip' => ['password'],
        'exclude_suffixes' => ['_error'],
        'formatters' => [
            'amount' => Formatters::currency('$')
        ]
    ])
    ->toFields();
```

### Helper Functions (Advanced)

[](#helper-functions-advanced)

The package provides `array_flatten_with_keys()` for general use:

```
$flat = array_flatten_with_keys([
    'user' => [
        'name' => 'John',
        'address' => ['city' => 'Lagos']
    ]
], '', ' → ');

// Result: ['user → name' => 'John', 'user → address → city' => 'Lagos']
```

Testing
-------

[](#testing)

Run the tests:

```
composer test
```

Or:

```
./vendor/bin/phpunit
```

Code Formatting
---------------

[](#code-formatting)

This package uses Laravel Pint for code formatting:

**Format code:**

```
composer format
```

**Check formatting without fixing:**

```
composer format:test
```

Or run Pint directly:

```
./vendor/bin/pint
```

Local Development
-----------------

[](#local-development)

To test this package locally in another Laravel project before publishing to Packagist:

Add to your project's `composer.json`:

```
"repositories": [
    {
        "type": "path",
        "url": "../json-to-keyvalue"
    }
],
"require": {
    "provydon/json-to-keyvalue": "*"
}
```

Then run:

```
composer update provydon/json-to-keyvalue
```

Publishing to Packagist
-----------------------

[](#publishing-to-packagist)

1. Push your code to GitHub
2. Go to [packagist.org](https://packagist.org) and sign in
3. Click "Submit" and paste your GitHub repository URL
4. Packagist will auto-update on each GitHub push (configure webhook for automation)

Users can then install via:

```
composer require provydon/json-to-keyvalue
```

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance65

Regular maintenance activity

Popularity25

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

3

Last Release

215d ago

Major Versions

v0.1.0 → v1.0.02025-10-09

### Community

Maintainers

![](https://www.gravatar.com/avatar/c596d5c1b7f297daa7dc1398beae75ea8f55ba06a89c2ef371cf3116df471673?d=identicon)[provydon](/maintainers/provydon)

---

Top Contributors

[![provydon](https://avatars.githubusercontent.com/u/31216637?v=4)](https://github.com/provydon "provydon (13 commits)")

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/provydon-json-to-keyvalue/health.svg)

```
[![Health](https://phpackages.com/badges/provydon-json-to-keyvalue/health.svg)](https://phpackages.com/packages/provydon-json-to-keyvalue)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
