provydon/json-to-keyvalue 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

provydon/json-to-keyvalue

最新稳定版本:v1.1.0

Composer 安装命令:

composer require provydon/json-to-keyvalue

包简介

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

README 文档

README

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

Why You Need This

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 Before - Nova KeyValue

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

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

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

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

Skip indices entirely or customize their format:

// Skip completely ->skipArrayIndices(true) // Use parentheses ->arrayIndexFormat(' (%d)') // Use brackets ->arrayIndexFormat(' [%d]')

More Control

Conditionally flatten arrays and control when to process large datasets:

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

Requirements

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

Installation

composer require provydon/json-to-keyvalue

Usage

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

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)

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)

For displaying key-value pairs outside of Nova:

<x-keyvalue-display :data="$jsonData" label="User Details" :config="['skip' => ['password']]" />

API Methods

Available Methods

Method Parameters Description
make($data, $label) data, label Create new instance
fromNestedArray($data, $formatter) array, ?callable Static method to iterate nested arrays
skip($keys) array Skip specific keys
excludeSuffixes($suffixes) array Exclude keys by suffix
excludePrefixes($prefixes) array Exclude keys by prefix
flattenNested($bool) boolean Enable/disable flattening
nestedSeparator($sep) string Set separator for nested keys
flattenSingleArrays($bool) boolean Auto-extract single-item arrays
skipArrayIndices($bool) boolean Skip adding array indices to labels
arrayIndexFormat($format) string Customize array index format (sprintf)
maxArraySize($size) ?int Only flatten arrays below this size
itemLabel($label) string Label for array items
labels($labels) array Custom field labels
formatters($formatters) array Custom formatters
lookups($lookups) array Database lookups
config($config) array Merge config array
toFields() - Return Nova fields
toArray() - Return plain arrays

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

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

  • 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

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

Publish the views:

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

Use in Blade templates:

<x-keyvalue-display :data="$user->metadata" label="User Metadata" :config="[  'skip' => ['password'],  'formatters' => [  'created_at' => fn($v) => $v->format('M d, Y')  ]  ]" />

Advanced Usage

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

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)

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

Run the tests:

composer test

Or:

./vendor/bin/phpunit

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

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

  1. Push your code to GitHub
  2. Go to 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

MIT

统计信息

  • 总下载量: 1.6k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 3
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-01-04

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固