แปลง multiple JSON object string ด้วย Python

สมมติว่าเรามี JSON object หลายๆ ตัวซ้อนกันอยู่ใน string แบบนี้ (multi line ด้วยอ่ะ ไม่งั้นล้นหน้า page wordpress)

json_string = = """
{"ID":1,"Key":{"Name":"A", "Surname":"A1"},"Pets":["Cat","Dog"]},
{"ID":9,"Key":{"Name":"Z", "Surname":"Z3"},"Pets":["Fish"]}
"""

ถ้าเรา convert มันให้กลายเป็น JSON object (จริงๆ คือ Python dict object) ด้วย json.loads(string) ตรงๆ ผลลัพท์ที่ได้จะบึ้มดังนี้

import json

json_string = = """
{"ID":1,"Key":{"Name":"A", "Surname":"A1"},"Pets":["Cat","Dog"]},
{"ID":9,"Key":{"Name":"Z", "Surname":"Z3"},"Pets":["Fish"]}
"""

json_obj = json.loads(json_string)

>>> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\lib\json\__init__.py", line 354, in load
s
    return _default_decoder.decode(s)
  File "...\lib\json\decoder.py", line 342, in decod
e
    raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 65 (char 64)

ทางแก้คือเราต้องทำให้ string ก้อนนั้นเป็น JSON array แล้วเราจะได้ array ของ JSON object มาวนแต่ละตัวได้

import json

json_string = """
[
    {"ID":1,"Key":{"Name":"A", "Surname":"A1"},"Pets":["Cat","Dog"]},
    {"ID":9,"Key":{"Name":"Z", "Surname":"Z3"},"Pets":["Fish"]}
]
"""

json_obj = json.loads(json_string)

print(json_obj[0])
>>> {'ID': 1, 'Key': {'Name': 'A', 'Surname': 'A1'}, 'Pets': ['Cat', 'Dog']}

print(json_obj2[1])
>>> {'ID': 9, 'Key': {'Name': 'Z', 'Surname': 'Z3'}, 'Pets': ['Fish']}

ป.ล. string ถ้าไม่ multi lines ก็ใช้วิธีเดียวกันนั่นแหละ

ป.ล. 2 เพิ่งเห็นว่าเจ้า Gutenberg editor นี่ช่องให้ code ไม่มีรองรับ code syntax, formatting โคตรกากกกกกก ห่วยกว่าเก่าอีก

วิธีสร้าง JSON Message ด้วย Java

ผมเขียนถึงวิธีการสร้าง JSON message บน Java ผ่าน entry นี้มาแล้วรอบนึง หลังจากนั้นผมก็ไปค้นเจอทีหลังว่าจริงๆ แล้ว Java มันสนับสนุน JSON โดยไม่ต้องพึ่ง 3rd Party lib แล้ว เลยมาแนะนำกันครับ

สิ่งที่ผมจะสร้างคือ JSON หน้าตาแบบนี้

{
   "service":"quote",
   "user":"plynoi",
   "symbols":["Nokia"],
   "fields":["BID","ASK","HIGH"]
}

ขอเปรียบเทียบกับวิธีใช้ 3rd Party ก่อน ตัวที่ผมเลือกเพราะ google เจออันดับแรกๆ คือ json-simple ซึ่งมันก็ใช้ง่ายๆ ตรงไปตรงมา doc อ่านง่ายดีมาก จะขอยกตัวอย่างตัดมาจาก entry Java อันนั้นอีกทีนะครับ

import org.json.simple.*;

private void createJSON(){

	JSONObject request_msg = new JSONObject();
	request_msg.put("service","quote");
        	request_msg.put("user","plynoi");

        	JSONArray itemArray = new JSONArray();
        	itemArray.add("Nokia");

        	JSONArray filterArray = new JSONArray();
        	filterArray.add("BID");
        	filterArray.add("ASK");
       	filterArray.add("HIGH");

        	request_msg.put("symbols",itemArray);
        	request_msg.put("fields",filterArray);
	
	//JSON message "request_msg" is ready to process
}

เทียบกับตัว Native ของ Java เองอย่าง JSR 353 แล้วส่วนตัวผมมองว่าที่ Java ให้มาอยู่แล้วยุ่งยากกว่าเยอะ แต่โชคดีที่ doc เขียนละเอียดดีโฮกๆ (แต่ก็อ่านยากกว่าเช่นกัน :p)

import javax.json.Json;
import javax.json.JsonObject;

private void createJSON(){

	JsonObject request_msg = Json.createObjectBuilder()
		.add("service","quote")
		.add("user","plynoi")
		.add("symbols",Json.createArrayBuilder()
                    		.add("Nokia")
               	 )
                	.add("fields",Json.createArrayBuilder()
                    		.add("BID")
                    		.add("ASK")
                    		.add("HIGH")
                	)
                .build();
	
	//JSON message "request_msg" is ready to process
}

จะไปใช้ตัวไหนก็แล้วแต่นะครับ ส่วนตัวผมชอบ simple-json มากกว่าตรงที่มันดูตรงไปตรงมากว่านี่แหละ

Python: post request with json

ออกตัวล้อฟรีก่อนว่าผมเขียนภาษา dynamic อยู่ 2 ภาษาคือ พอจะเขียน python ได้บ้าง (งาน script เล็กๆ แทน shellscript หรือเขียน process log file เพื่อเสริมการทำงาน) และภาษา javascript ซึ่งใช้ทำงานจริงจังมา 2 ปี

ปลายปีที่แล้วมีงานที่ต้องลอง reproduce ปัญหาด้วยการยิง http post request ที่มี input เป็น json format เพื่อดูผลการทำงานของ server อยู่บ่อยๆ เลยต้องหาวิธียิง request แบบง่ายๆ ซึ่งคิดไว้ 3 ทางคือ

  • ใช้ jQuery.ajax เขียน ก็ใช้เวลาไม่นาน
  • ใช้ Advanced REST client plugin บน Chrome ก็ได้
  • ใช้ RESTClient ของ Firefox ก็ได้

แต่ทุกตัวต้องมาเปิด browser อะไรยุ่งยาก เลยหาวิธีเขียนบน python รันแค่ cmd แล้วรัน script ก็น่าจะได้ผลเร็วกว่าเปิด browser พวกนี้ ก็เลยไปค้นๆ google มา

วิธีแรกใช้ lib Requests

import requests
import json

payload={'service':'QUOTE','subject':'AAPL'}
url='http://1xx.xx.xxx.xxx:8080/quote'
headers = {'content-type': 'application/json'}
r = requests.post(url, data=json.dumps(payload), headers=headers)
print r.json

สิ่งที่ผมลืมไปคือหลังๆ ผมติด json บน javascript ที่ key ไม่จำเป็นต้องเป็น string ซึ่งมันขัดกับ dictionary ของ python เลยงงๆ อยู่สักพักก็ได้ http request แบบง่ายๆ ขึ้นมา script นึง

ไอ้ script ที่แล้วใช้ 3rd party lib เลยอยากลองแบบ python lib เพียวๆ ดูบ้าง ลองค้นๆ วิธีดูสักพักก็ได้เจ้าตัวนี้มา

import urllib2
import json

payload=json.dumps({'closure':'Python test tool','service':'Chart','subject':['AAPL']})
headers = {'content-type': 'application/json'}
req = urllib2.Request(url='http://1xx.xx.xxx.xxx:8080/chart',data=payload,headers=headers)
f=urllib2.urlopen(req)
print f.read()
f.close()

จะเห็นว่า code ยุ่งยากขึ้นอย่างเห็นได้ชัด แต่ก็ค่อนข้างจะ simple ตามสไตล์ python อยู่ดี

ป.ล. ผมเคยลองหาข้อมูล python call webservice (xml, soap พวกนั้น) เพื่อใช้ทำ script test แต่พบว่ามันยากเย็นแสนเข็ญจนตัดใจไปใช้ soapui แทน