Tiêu đề kiểu nội dung HTTP và JSON


144

Tôi đã luôn cố gắng tránh sử dụng hầu hết các thuộc tính của giao thức HTTP vì sợ không biết.

Tuy nhiên, tôi đã nói với bản thân mình rằng hôm nay tôi sẽ đối mặt với nỗi sợ hãi và bắt đầu sử dụng các tiêu đề một cách có chủ đích. Tôi đã cố gắng gửi jsondữ liệu đến trình duyệt và sử dụng nó ngay lập tức. Ví dụ: nếu tôi có hàm xử lý Ajax ở trạng thái sẵn sàng 4 trông giống như vậy:

function ajaxHandler(response){
    alert(response.text);
}

Và tôi đã đặt tiêu đề loại nội dung trong mã PHP của mình:

header('Content-Type: application/json');
echo json_encode(array('text' => 'omrele'));

Tại sao tôi không thể truy cập trực tiếp vào tài sản từ chức năng xử lý, khi trình duyệt được thông báo rõ ràng rằng dữ liệu đến là application/json?


Nếu tôi hiểu chính xác, bạn muốn sử dụng textnhư một biến javascript trong trình xử lý và không phản hồi? Đó sẽ là chức năng rất kỳ lạ. Json_encode cũng tạo 1 đối tượng trong mảng PHP của bạn. Vì vậy, khi bạn nhận được điều này vào javascript, nó cần phải được gán cho một biến.
Flashin

4
Tiêu đề contentType chỉ là thông tin. Trình duyệt sẽ sử dụng nó nếu có thể, nhưng trong trường hợp này, các trình duyệt chỉ cần bỏ qua nó vì họ thường không biết ý định đó là gì. Ứng dụng Javascript của bạn có thể sử dụng nó. Bạn đang giả sử rằng JSON sẽ được trình bày, vì vậy bạn có thể giải mã nó với JSON.parse(). Bạn có thể thực hiện một số hành động khác nhau hoặc buộc lỗi nếu xuất hiện nội dung sai.

1
Trình duyệt không tự động phân tích văn bản JSON cho bạn, do đó response.textvẫn là một chuỗi.
nnnnnn

1
Vì vậy, bạn có nghĩa là để nói với tôi rằng thiết lập tiêu đề đó không có gì khác biệt bao giờ? Mục đích của sự tồn tại sau đó là gì?
php_nub_qq

2
@php_nub_qq: Mục đích của nó là cho bạn biết những gì máy chủ trả về để ứng dụng của bạn có thể xử lý nó phù hợp. Các trình duyệt sẽ không phân tích cú pháp JSON cho bạn, ứng dụng của bạn cần phải làm điều đó. Tiêu đề này cho bạn biết rằng đó là (hoặc nên là JSON).
Tên lửa Hazmat

Câu trả lời:


136

Các Content-Typetiêu đề chỉ được sử dụng như thông tin cho ứng dụng của bạn. Trình duyệt không quan tâm nó là gì. Trình duyệt chỉ trả về cho bạn dữ liệu từ cuộc gọi AJAX. Nếu bạn muốn phân tích nó dưới dạng JSON, bạn cần phải tự làm điều đó.

Tiêu đề là ở đó để ứng dụng của bạn có thể phát hiện dữ liệu nào được trả về và cách xử lý dữ liệu đó. Bạn cần nhìn vào tiêu đề và nếu nó application/jsonthì phân tích nó thành JSON.

Đây thực sự là cách jQuery hoạt động. Nếu bạn không cho nó biết phải làm gì với kết quả, nó sẽ sử dụng Content-Typeđể phát hiện những việc cần làm với nó.


12
Điều đó không hoàn toàn đúng. Nếu bạn không sử dụng header('Content-Type: application/json');và buộc tải xuống Content-Disposition: attachment; filename=myfile.jsonthì bạn sẽ kết thúc bằng một myfile.json.html. Sử dụng tiêu đề json này, bạn sẽ nhận được myfile.json.
Remi Grumeau

4
@RemiGrumeau Điều gì là 'không hoàn toàn đúng'? Tải tập tin bằng trình duyệt là một cái gì đó hoàn toàn khác. Trình duyệt có thể sẽ mặc định mong đợi HTML, vì vậy nó giả định mọi thứ nó nhận được là HTML trừ khi có quy định khác. Khi tải xuống, nó sẽ thêm .htmlvào tệp, vì đó là những gì nó mặc định.
bzeaman

2
Tôi không biết toàn bộ bối cảnh của vấn đề ở đây - NHƯNG, trình duyệt (và javascript) đôi khi quan tâm đến Kiểu nội dung. Tiêu đề này có thể tác động đến các heuristic mà trình duyệt sử dụng để hiển thị nội dung và gửi XML và JSON bằng một loại văn bản / html nội dung thường có thể tạo ra các lỗi tinh vi trong các yêu cầu XHR cơ bản (hoặc các lớp khung của bạn trên đầu trang)
Alan Storm

7

Content-Type: application/jsonchỉ là tiêu đề nội dung. Tiêu đề nội dung chỉ là thông tin về loại dữ liệu được trả về, ví dụ: JSON, hình ảnh (png, jpg, v.v.), html.

Hãy nhớ rằng JSON trong JavaScript là một mảng hoặc đối tượng. Nếu bạn muốn xem tất cả dữ liệu, hãy sử dụng console.log thay vì cảnh báo:

alert(response.text); // Will alert "[object Object]" string
console.log(response.text); // Will log all data objects

Nếu bạn muốn cảnh báo nội dung JSON gốc dưới dạng chuỗi, sau đó thêm dấu ngoặc kép ('):

echo "'" . json_encode(array('text' => 'omrele')) . "'";
// alert(response.text) will alert {"text":"omrele"}

Không sử dụng dấu ngoặc kép. Nó sẽ gây nhầm lẫn cho JavaScript, vì JSON sử dụng dấu ngoặc kép trên mỗi giá trị và khóa:

echo '<script>var returndata=';
echo '"' . json_encode(array('text' => 'omrele')) . '"';
echo ';</script>';

// It will return the wrong JavaScript code:
<script>var returndata="{"text":"omrele"}";</script>

Không bao giờ làm điều này, nó sẽ phá vỡ bất kỳ chuỗi nào bằng cách sử dụng các dấu ngoặc đơn (và nó thường xuyên ở nhiều ngôn ngữ): echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; sẽ tạo ra đầu ra bị hỏng này : '{"text":"it's wrong"}'. Sử dụng cái này thay thế : json_encode(json_encode(array('text' => 'it\'s good'))). Kết quả sẽ được thoát chính xác:"{\"text\":\"it's wrong\"}"
PofMagicfingers 11/03/19

1

Đoạn mã dưới đây giúp tôi trả về một đối tượng JSON cho JavaScript ở mặt trước

Mã mẫu của tôi

template_file.json

{
    "name": "{{name}}"
}

Mã được hỗ trợ bởi Python

def download_json(request):
    print("Downloading JSON")
    # Response render a template as JSON object
    return HttpResponse(render_to_response("template_file.json",dict(name="Alex Vera")),content_type="application/json")    

Tệp url.py

url(r'^download_as_json/$', views.download_json, name='download_json-url')

Mã jQuery cho giao diện người dùng

  $.ajax({
        url:'{% url 'download_json-url' %}'        
    }).done(function(data){
        console.log('json ', data);
        console.log('Name', data.name);
        alert('hello ' + data.name);
    });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.