在 Laravel 中从数据库存储和加载 JSON 的最佳方法

我正在尝试将 json 存储到数据库中并将其加载回来

我试图存储

{name: "John", age: 31, city: "New York"}

它存储正确。我检查了数据库,它显示正确。

{姓名:“约翰”,年龄:31,城市:“纽约”}

我一直在看风景

"{name: "John", age: 31, city: "New York"}"

这是我的代码。

public function store()
{

    $paste             = new Paste;
    $paste->uuid       = Str::uuid()->toString();
    $paste->data       = trim(Request::get('data',''));
    $paste->save();

    return Redirect::to('/paste/'.$paste->uuid)->with('success', 'Created');

}

public function show($uuid)
{
    $paste  = Paste::where('uuid',$uuid)->first();
    return response()->json($paste->data);
}

对我有什么提示吗?

可在此处重现

https://www.bunlongheng.com/paste


试试#2

如果我这样做

public function show($uuid)
{

    $paste  = Paste::where('uuid',$uuid)->first();
    return View::make('layouts.fe.pastes.show', get_defined_vars());

}

在我看来,我只有这 1 行

{!!$paste->data!!}

我得到的数据与我现在提交的数据相同。

{name: "John", age: 31, city: "New York"}

但是浏览器将其检测为文本,而不是响应 JSON,这违背了我想要做的事情的目的。


试试#3

public function show($uuid)
{
    $paste  = Paste::where('uuid',$uuid)->first();
    return response()->json(stripslashes($paste->data));

}

结果

"{name: "John", age: 31, city: "New York"}"

试试#4

public function show($uuid)
{
    $paste  = Paste::where('uuid',$uuid)->first();
    return View::make('layouts.fe.pastes.show', get_defined_vars());
}

看法

{{ json_encode($paste->data, JSON_UNESCAPED_SLASHES) }}

结果

"{name: "John", age: 31, city: "New York"}"

尝试#5

我认为问题在于存储......而不是加载和渲染。

我试过了

return response()->json($paste);

我的 JSON 解析器检测到它...

enter image description here

{
"id": 11,
"status": 0,
"uuid": "0c40f97d-7d98-42c6-864e-71d3ed81eed3",
"name": "n6ou",
"password": "",
"expiration": "",
"type": "json",
"data": "{name: "John", age: 31, city: "New York"}",
"created_at": "2021-04-22T22:53:11.000000Z",
"updated_at": "2021-04-22T22:53:11.000000Z"
}

这是我以前储存的

$paste->data       = trim(Request::get('data',''));
$paste->save();

尝试#6

对于那些怀疑我的数据/内容的人

我尝试在 Pastebin 中粘贴同一行

enter image description here

已清理完毕,您可以在下面看到。

https://pastebin.com/raw/r9akUK1v

stack overflow Best way to store and load JSON from database in Laravel
原文答案
author avatar

接受的答案

数据库

在您的数据库迁移中添加:

$table->json('data'); // Recommended. Supported in MySQL since version 5.7.8

或者

$table->text('data');

建议使用 JSON 列类型,因为它允许您对 JSON 数据执行 SQL 查询。见 MySQL JSON Data Type

模型:铸造属性

下一个问题是您需要能够将数据转换为 PHP 数组。

这是通过修改模型中的 casts 属性来完成的:

class Paste extends Model {
    protected $casts = [
        'data' => 'array'
    ];
}

有关详细信息,请参阅 Array and JSON Casting

现在您可以将数据作为 PHP 数组保存到属性中,并为其分配一个 PHP 数组。

 $paste = Paste::first();
 dump($paste); // Returns a PHP array     

 $paste->data = ['some-data' => 20, 'score' => 500];
 $paste->save();

在内部,当它保存数据时,它会自动将其转换为 JSON 字符串并以正确的格式保存在数据库中。

存储方法

将输入作为 JSON 接收时,很大程度上取决于您希望如何传递数据,

1。发送 JSON 内容类型的表单数据(推荐)

我的建议是在 POST 正文中将整个数据作为 JSON 发送,如下所示:

Content-Type: application/json
Body:
{
   "data": {
      "name": "John",
      "age": 31,
      "city": "New York"
   },
   "someOtherField": "Hello!"
}

您的 store() 方法现在应该是(我还添加了验证代码):

public function store()
{
    $this->validate($request, [
        'data' => ['required', 'array'],
        'data.*.name' => ['required', 'string'],
        'data.*.age' => ['required', 'int'],
        'data.*.city' => ['required', 'string'],
    ]);

    $paste = new Paste();
    $paste->uuid = Str::uuid()->toString();
    $paste->data = $request->post('data'); // No need to decode as it's already an array
    $paste->save();

    return Redirect::to("/paste/{$paste->uuid}")
        ->with('success', 'Created');
}

2。使用表单参数发送表单数据

但是,如果您坚持通过查询参数或表单参数发送数据,请注意这些只能发送字符串。因此,您需要发送 JSON 字符串的编码版本来持久化数据类型,如下所示:

Form Params:
- data: '{"name": "John", "age": 31, "city": "New York"}'
- someOtherField: "Hello!"

store 方法现在看起来像这样:

    $this->validate($request, [
        'data' => ['required', 'json'], // I'm unsure if data is required
    ]);

    $data = json_decode($request->post('data'), true, JSON_THROW_ON_ERROR); // Needs to be decoded

    // validate $data is correct
    Validator::make($data, [
        'name' => ['required', 'string'],
        'age' => ['required', 'int'],
        'city' => ['required', 'string'],
    ])->validate();

    $paste = new Paste();
    $paste->uuid = Str::uuid()->toString();
    $paste->data = $data;
    $paste->save();

    return Redirect::to("/paste/{$paste->uuid}")
        ->with('success', 'Created');

显示方法

您的 show 方法不需要更改:

public function show($uuid)
{
    $paste = Paste::where('uuid', $uuid)->first();
    return response()->json($paste->data);
}

答案:

作者头像

1-您的列需要是 json 类型

$table->json('data');

2-在您的模型中,您需要将列转换为数组

  protected $casts = ['data' => 'array'];

3-向控制器发送数据值必须是一个数组,以便您可以在其上使用数组 Laravel 验证:

[
  'data' => 'required|array',
  'data.*.name' => 'required'
   ....
]

4-当您存储数据时,它将被自动解析,当您检索数据列时,它将被转换为数组

作者头像

1.使用 ->json() 作为存储JSON数据的迁移方式( https://laravel.com/docs/8.x/migrations#column-method-json

  1. 参考“Array & JSON Casting”( https://laravel.com/docs/8.x/eloquent-mutators#array-and-json-casting )了解如何准备数据

我知道答案不像其他人那样在段落中,但我喜欢让它简单明了。这是最好的解决方案吗?没有人能告诉你,也不能证明这一点?这种方法是否行得通,没有人能告诉你,也没有人能证明这一点,但至少它会提高你的成功率。让我知道是否还有什么我可以帮助的!祝你好运

作者头像

如果您想将数据作为 json 存储在 DB 上并恢复它,只需执行以下操作(我总是使用这种方式):

1-将您的数据添加到数组:

$data["name"] = "John";
$data["age"] = 31;
$data["city"] = "New York";

2-对数组进行编码并将其添加到数据库中(您可以将其存储为文本)

$encodedData = json_encode($data);

3-如果你想添加嵌套的 json 数据,只需让你的数组嵌套数组。

4-当您恢复数据时,只需使用 json_decode 对其进行解码

作者头像

只需将其添加到您的模型中。

protected $casts = [
    'data' => 'object'
];

然后,您可以这样看待您的观点:

{{ $data->data->name }}