ส่วนหัวของประเภทเนื้อหา HTTP และ JSON


144

ฉันพยายามหลีกเลี่ยงการใช้คุณสมบัติของโปรโตคอล HTTP เกือบทุกครั้งเพื่อที่จะกลัวความไม่รู้จัก

อย่างไรก็ตามฉันพูดกับตัวเองว่าฉันจะต้องเผชิญหน้ากับความกลัวในวันนี้และเริ่มใช้ส่วนหัวอย่างเด็ดเดี่ยว ฉันพยายามส่งjsonข้อมูลไปยังเบราว์เซอร์และใช้งานได้ทันที ตัวอย่างเช่นถ้าฉันมีฟังก์ชั่น Ajax handler ในสถานะ Ready 4 ซึ่งมีลักษณะดังนี้:

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

และฉันได้ตั้งหัวข้อประเภทเนื้อหาในรหัส PHP ของฉัน:

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

ทำไมฉันไม่สามารถเข้าถึงได้โดยตรงจากสถานที่ให้ฟังก์ชั่นการจัดการเมื่อเบราว์เซอร์จะบอกอย่างชัดเจนว่าข้อมูลที่เข้ามาเป็นapplication/json?


หากฉันเข้าใจถูกต้องคุณต้องการใช้textเป็นตัวแปรจาวาสคริปต์ในตัวจัดการและไม่ตอบสนอง? นั่นจะเป็นฟังก์ชั่นที่แปลกมาก json_encode สร้างวัตถุ 1 รายการจากอาร์เรย์ PHP ของคุณ ดังนั้นเมื่อคุณได้รับสิ่งนี้ลงในจาวาสคริปต์จะต้องมีการกำหนดให้กับตัวแปร
Flashin

4
ส่วนหัว contentType เป็นข้อมูลเท่านั้น เบราว์เซอร์จะใช้สิ่งนั้นหากทำได้ แต่ในกรณีนี้เบราว์เซอร์จะเพิกเฉยเพราะพวกเขามักไม่รู้ว่าเจตนาคืออะไร แอปพลิเคชัน Javascript ของคุณสามารถใช้ประโยชน์ได้ คุณกำลังสมมติว่า JSON JSON.parse()จะนำเสนอเพื่อให้คุณสามารถถอดรหัสได้ด้วย คุณสามารถดำเนินการต่าง ๆ หรือบังคับให้เกิดข้อผิดพลาดหาก contentType ผิดพลาดปรากฏขึ้น

1
เบราว์เซอร์ไม่แยกวิเคราะห์ข้อความ JSON ให้คุณโดยอัตโนมัติดังนั้นจึงresponse.textยังคงเป็นสตริง
nnnnnn

1
ดังนั้นคุณต้องบอกฉันว่าการตั้งค่าส่วนหัวนั้นไม่สร้างความแตกต่างอะไรเลย จุดประสงค์ของการดำรงอยู่คืออะไร?
php_nub_qq

2
@php_nub_qq: มีวัตถุประสงค์เพื่อแจ้งให้คุณทราบถึงสิ่งที่เซิร์ฟเวอร์ส่งคืนเพื่อให้แอปพลิเคชันของคุณสามารถจัดการได้ เบราว์เซอร์จะไม่แยก JSON สำหรับคุณแอปของคุณต้องการที่จะทำเช่นนั้น ส่วนหัวนี้จะบอกคุณว่ามันเป็น (หรือควรเป็น JSON)
จรวดแฮซแมท

คำตอบ:


136

Content-Typeส่วนหัวถูกนำมาใช้เช่นเดียวกับข้อมูลสำหรับการใช้งานของคุณ เบราว์เซอร์ไม่สนใจว่ามันคืออะไร เบราว์เซอร์เพิ่งส่งคืนข้อมูลจากการโทร AJAX ให้คุณ หากคุณต้องการแยกมันเป็น JSON คุณต้องทำด้วยตัวเอง

ส่วนหัวอยู่ที่นั่นเพื่อให้แอปของคุณสามารถตรวจสอบข้อมูลที่ถูกส่งคืนและวิธีจัดการกับมัน คุณต้องดูที่ส่วนหัวและถ้าเป็นเช่นapplication/jsonนั้นก็แยกวิเคราะห์เป็น JSON

นี่คือวิธีการทำงานของ jQuery หากคุณไม่บอกว่าจะทำอย่างไรกับผลลัพธ์มันจะใช้การContent-Typeตรวจสอบว่าจะทำอย่างไรกับมัน


12
นั่นไม่จริงทั้งหมด หากคุณไม่ได้ใช้header('Content-Type: application/json');และมีผลบังคับใช้ในการดาวน์โหลดได้แล้วคุณจะจบลงด้วยContent-Disposition: attachment; filename=myfile.json myfile.json.htmlโดยใช้ส่วนหัว JSON myfile.jsonนี้คุณจะได้รับ
Remi Grumeau

4
@RemiGrumeau 'ไม่จริงทั้งหมด' คืออะไร การดาวน์โหลดไฟล์ด้วยเบราว์เซอร์เป็นสิ่งที่แตกต่างอย่างสิ้นเชิง เบราว์เซอร์อาจเป็นค่าเริ่มต้นที่คาดว่าจะ HTML ดังนั้นจึงถือว่าสิ่งที่ได้รับคือ HTML เว้นแต่จะระบุไว้เป็นอย่างอื่น เมื่อดาวน์โหลดไฟล์จะผนวก.htmlเข้ากับไฟล์เพราะนั่นคือค่าเริ่มต้น
bzeaman

2
ฉันไม่ทราบบริบททั้งหมดของปัญหาที่นี่ - แต่เบราว์เซอร์ (และจาวาสคริปต์) ให้ความสำคัญกับเนื้อหา - บางครั้ง ส่วนหัวนี้สามารถส่งผลกระทบต่อพฤติกรรมที่เบราว์เซอร์ใช้เพื่อแสดงเนื้อหาและการส่ง XML และ JSON ด้วยประเภทเนื้อหาของข้อความ / html มักจะสามารถสร้างข้อบกพร่องที่ลึกซึ้งในคำขอ XHR พื้นฐาน (หรือเลเยอร์ของกรอบด้านบนของพวกเขา)
Alan Storm

7

Content-Type: application/jsonเป็นเพียงส่วนหัวของเนื้อหา ส่วนหัวของเนื้อหาเป็นเพียงข้อมูลเกี่ยวกับประเภทของข้อมูลที่ส่งคืนเช่น :: JSON, รูปภาพ (png, jpg, ฯลฯ .. ), html

โปรดทราบว่า JSON ใน JavaScript นั้นเป็นอาร์เรย์หรือวัตถุ หากคุณต้องการดูข้อมูลทั้งหมดให้ใช้ console.log แทนการแจ้งเตือน:

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

หากคุณต้องการแจ้งเตือนเนื้อหา JSON ดั้งเดิมเป็นสตริงให้เพิ่มเครื่องหมายคำพูดเดี่ยว ('):

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

อย่าใช้เครื่องหมายคำพูดคู่ มันจะสับสน JavaScript เนื่องจาก JSON ใช้เครื่องหมายคำพูดคู่ในแต่ละค่าและคีย์:

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>

ไม่เคยทำเช่นนี้ก็จะทำลายในสตริงใด ๆ โดยใช้ราคาเดียว (และก็บ่อยครั้งในหลายภาษา): จะผลิตออกเสียนี้:echo "'" . json_encode(array('text' => 'it\'s wrong')) . "'"; '{"text":"it's wrong"}'ใช้สิ่งนี้แทน: json_encode(json_encode(array('text' => 'it\'s good'))). ผลลัพธ์จะได้รับการหลบหนีอย่างถูกต้อง:"{\"text\":\"it's wrong\"}"
PofMagicfingers

1

รหัสด้านล่างช่วยให้ฉันกลับวัตถุ JSON สำหรับ JavaScript ที่ปลายด้านหน้า

รหัสแม่แบบของฉัน

template_file.json

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

รหัสที่ได้รับการสนับสนุน 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")    

ไฟล์ url.py

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

รหัส jQuery สำหรับส่วนหน้า

  $.ajax({
        url:'{% url 'download_json-url' %}'        
    }).done(function(data){
        console.log('json ', data);
        console.log('Name', data.name);
        alert('hello ' + data.name);
    });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.