在Laravel中存储和加载JSON的最佳方法

13
我正在尝试将JSON存储到数据库中并加载回来。
我尝试进行存储。
{name: "John", age: 31, city: "New York"}

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

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

我一直在视图上遇到问题。

"{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());

}

在我看来,我只有这一行{{占位符}}。

{!!$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


1
尝试使用 return response()->json(stripslashes($paste->data)); - Ivan86
1
或者,您可以尝试这样写:{ json_encode($paste->data, JSON_UNESCAPED_SLASHES) } - Ivan86
尝试两种方式,斜杠仍然存在。 - code-8
控制器代码长什么样? - code-8
return response()->json($paste->data); && {{ json_decode($paste->data) }} - code-8
显示剩余24条评论
5个回答

19

数据库

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

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

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

模型:转换属性

下一个问题是您需要能够将数据转换为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内容类型发送表单数据(推荐)

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

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');

显示方法

您的显示方法不需要更改:

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

这一行代码 $data = json_decode($request->post('data')); 一直将我的数据输入JSON转换为null。 - code-8
你是怎么调用你的API的?可以展示一下你的JavaScript或curl代码吗? - Yahya Uddin
如果您正在使用查询字符串,那么代码应该是 $request->query('data') - Yahya Uddin
1
我已经更新了这行代码。在第二个参数中没有设置为true,犯了一个小错误。如果数据不是有效的JSON字符串,它也不会抛出错误。 - Yahya Uddin

4

1- 您的列需要是json类型

$table->json('data');

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

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

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

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

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


让我试试那个建议。 - code-8
我认为这种方法是处理JSON数据的最佳方式。有一个要补充的地方(假设OP使用MySQL数据库):旧版MySQL服务器不支持JSON类型。所以,MySQL <= 5.7的版本应该使用LONGTEXT代替。 - Gordon Freeman
@GordonFreeman 对于旧版本来说,longText是解决方案,但在这种情况下我不确定elequont是否适用。 - PsyLogic
@PsyLogic,Eloquent 处理这个问题没问题。在旧项目中也没有遇到过问题。protected $casts 可以处理魔法,不考虑实际的 DB 字段类型。唯一的缺点是我能想到的,无法从 DB 级别受益于 JSON 类型字段(在 JSON 中搜索等)。 - Gordon Freeman
感谢确认,但是由于JSON方法已添加到5.7+,所以它不适用于搜索,因此您需要在数据库中使用自定义函数或返回列值并在后端进行搜索(这不是推荐的做法)。 - PsyLogic

2
  1. 使用->json()作为迁移方法来存储JSON数据(https://laravel.com/docs/8.x/migrations#column-method-json)。
  2. 参考"数组和JSON转换"(https://laravel.com/docs/8.x/eloquent-mutators#array-and-json-casting)来准备数据。

我知道答案不像其他的段落那样详细,但我喜欢简单直接。这是最好的解决方案吗?没有人能告诉你,也无法证明。这种方法会起作用吗?没有人能告诉你,也无法证明,但至少可以增加成功率。如果还有其他需要帮助的地方,请告诉我!祝你好运!


0

只需将此添加到您的模型中即可。

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

然后你可以在视图中像这样获取:

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

0
如果您想将数据存储为json格式并在数据库中恢复它,请按照以下步骤操作(我总是使用这种方式):
1- 将您的数据添加到数组中:
$data["name"] = "John";
$data["age"] = 31;
$data["city"] = "New York";

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

$encodedData = json_encode($data);

3- 如果您想添加嵌套的JSON数据,只需将数组嵌套即可。

4- 恢复数据时,只需使用 json_decode 进行解码即可。


我必须根据用户提供的信息进行存储...请阅读我的帖子。 - code-8
抱歉,我给你这个方法是因为你说问题出在存储上。来自请求的Json数据默认情况下没有问题,但如果问题仍然存在,您可以使用它来填充响应数据到视图。 - Abdulgani Almonifi
请提供JSON文本。 - code-8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接