Laravel返回的JSON中文编码处理

2,353 阅读1分钟

1、问题描述

  • Laravel中返回的json默认对中文进行unicode编码,如果部分互联系统不接收unicode,如何解决?
  • 实际操作中发现Laravel自身的Controller和使用了DingoController-API处理方式也不一样

2、解决Laravel自身的Controller思路

  • 在控制器中直接写
public function common(Request $request)
{
    $headers = array(
        'Content-Type' => 'application/json; charset=utf-8'
    );
    $retData = [
        '姓名' => '张三',
        'birthdate' => '2010-02-15',
        '性别' => '男性',
    ];
    return \Response::json($retData, 200, $headers, JSON_UNESCAPED_UNICODE);
}
  • 写一个中间件,控制器或路由组中使用该中间件
namespace App\Http\Middleware;

use Closure;

class DistSjlApiAuth
{
    /**
     * @desc JSON序列化时不对中文进行Unicode编码
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        //其他逻辑

        $data = $next($request);

        if ($data instanceof \Illuminate\Http\JsonResponse) {
            $data->setEncodingOptions(JSON_UNESCAPED_UNICODE);
        }

        return $data;
    }
}

3、解决DingoController-API思路

  • 重写Json类,在配置文件config/api.php中修改formats.json项。
  • 重写Json类其实主要是重写filterJsonEncodeOptions这个方法,JsonOptionalFormatting这个traitfilterJsonEncodeOptions方法必须与[JSON_PRETTY_PRINT]取交集,改为与[JSON_PRETTY_PRINT, JSON_UNESCAPED_UNICODE,]取交集,encode方法中的$jsonEncodeOptions加入项[JSON_UNESCAPED_UNICODE].
<?php

namespace App\Helpers\Api;

use Dingo\Api\Http\Response\Format\Format;
use Dingo\Api\Http\Response\Format\JsonOptionalFormatting;
use Illuminate\Support\Str;
use Illuminate\Contracts\Support\Arrayable;

class Json extends Format
{
    /*
     * JSON format (as well as JSONP) uses JsonOptionalFormatting trait, which
     * provides extra functionality for the process of encoding data to
     * its JSON representation.
     */
    use JsonOptionalFormatting;

    /**
     * Format an Eloquent model.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     *
     * @return string
     */
    public function formatEloquentModel($model)
    {
        $key = Str::singular($model->getTable());

        if (! $model::$snakeAttributes) {
            $key = Str::camel($key);
        }

        return $this->encode([$key => $model->toArray()]);
    }

    /**
     * Format an Eloquent collection.
     *
     * @param \Illuminate\Database\Eloquent\Collection $collection
     *
     * @return string
     */
    public function formatEloquentCollection($collection)
    {
        if ($collection->isEmpty()) {
            return $this->encode([]);
        }

        $model = $collection->first();
        $key = Str::plural($model->getTable());

        if (! $model::$snakeAttributes) {
            $key = Str::camel($key);
        }

        return $this->encode([$key => $collection->toArray()]);
    }

    /**
     * Format an array or instance implementing Arrayable.
     *
     * @param array|\Illuminate\Contracts\Support\Arrayable $content
     *
     * @return string
     */
    public function formatArray($content)
    {
        $content = $this->morphToArray($content);

        array_walk_recursive($content, function (&$value) {
            $value = $this->morphToArray($value);
        });

        return $this->encode($content);
    }

    /**
     * Get the response content type.
     *
     * @return string
     */
    public function getContentType()
    {
        return 'application/json';
    }

    /**
     * Morph a value to an array.
     *
     * @param array|\Illuminate\Contracts\Support\Arrayable $value
     *
     * @return array
     */
    protected function morphToArray($value)
    {
        return $value instanceof Arrayable ? $value->toArray() : $value;
    }

    /**
     * Encode the content to its JSON representation.
     *
     * @param mixed $content
     *
     * @return string
     */
    protected function encode($content)
    {
        $jsonEncodeOptions = [JSON_UNESCAPED_UNICODE];

        // Here is a place, where any available JSON encoding options, that
        // deal with users' requirements to JSON response formatting and
        // structure, can be conveniently applied to tweak the output.

        if ($this->isJsonPrettyPrintEnabled()) {
            $jsonEncodeOptions[] = JSON_PRETTY_PRINT;
        }

        $encodedString = $this->performJsonEncoding($content, $jsonEncodeOptions);

        if ($this->isCustomIndentStyleRequired()) {
            $encodedString = $this->indentPrettyPrintedJson(
                $encodedString,
                $this->options['indent_style']
            );
        }

        return $encodedString;
    }

    /**
     * Filter JSON encode options array against the whitelist array.
     *
     * @param array $jsonEncodeOptions
     *
     * @return array
     */
    protected function filterJsonEncodeOptions(array $jsonEncodeOptions)
    {
        return array_intersect($jsonEncodeOptions, [JSON_PRETTY_PRINT, JSON_UNESCAPED_UNICODE,]);
    }

}