json modülü varsayılan olarak aşağıdaki türlerin kodlama (encoding) ve kod çözme (decoding) işlemlerini gerçekleştirir.
De-serialization türleri:
JSON | Python | |
---|---|---|
nesne | dict | |
array | list | |
string | str | |
sayı (int) | int | |
sayı (real) | float | |
true, false | True, False | |
null | None |
json modülü ayrıca NaN, Infinity ve -Infinity değerlerini karşılık gelen float değerleri olarak anlar ki bu JSON spesifikasyonunun dışındadır.
Serialization türleri:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number (int) |
True, False | true, false |
None | null |
NaN, Infinity ve -Infinity kodlamasına izin vermemek için allow_nan=False ile kodlamanız gerekir. Bu durumda, bu değerleri kodlamaya çalışırsanız bir ValueError oluşacaktır.
Özel deserialization-serialization
Farklı şekilde temsil edilmesi gereken verileri işlemenize olanak tanıyan çeşitli kancalar vardır. functools.partial kullanımı, kolaylık sağlamak için ilgili parametreleri bu fonksiyonlara kısmen uygulamanıza olanak tanır.
Serialization:
Nesneler serileştirilmeden önce nesneler üzerinde çalışan bir işlev sağlayabilirsiniz:
# my_json module
import json
from functools import partial
def serialise_object(obj):
# Json serileştirilebilir veri üretmek için bir şeyler yapın
return dict_obj
dump = partial(json.dump, default=serialise_object)
dumps = partial(json.dumps, default=serialise_object)
de-serialization:
json fonksiyonları tarafından işlenen object_hook ve parse_float gibi çeşitli kancalar vardır. Python sürümünüz için kapsamlı bir liste için buraya bakın.
# my_json module
import json
from functools import partial
def deserialise_object(dict_obj):
# Özel bir şey yap
return obj
def deserialise_float(str_obj):
# Özel bir şey yap
return obj
load = partial(json.load, object_hook=deserialise_object, parse_float=deserialise_float)
loads = partial(json.loads, object_hook=deserialise_object, parse_float=deserialise_float)
Daha fazla özel deserialization-serialization
json modülü ayrıca çeşitli türleri işlemek için json.JSONEncoder ve json.JSONDecoder’ın genişletilmesine/değiştirilmesine izin verir. Yukarıda belgelenen kancalar, eşdeğer şekilde adlandırılmış bir yöntem oluşturularak varsayılan olarak eklenebilir. Bunları kullanmak için ilgili fonksiyona cls parametresi olarak sınıfı geçirmeniz yeterlidir. functools.partial kullanımı, kolaylık sağlamak için cls parametresini bu fonksiyonlara kısmen uygulamanıza olanak tanır, örn.
# my_json module
import json
from functools import partial
class MyEncoder(json.JSONEncoder):
# Özel bir şey yap
class MyDecoder(json.JSONDecoder):
# Özel bir şey yap
dump = partial(json.dump, cls=MyEncoder)
dumps = partial(json.dumps, cls=MyEncoder)
load = partial(json.load, cls=MyDecoder)
loads = partial(json.loads, cls=MyDecoder)
Verilerin bir dosyada saklanması
Aşağıdaki kod parçacığı d’de saklanan verileri JSON’a kodlar ve bir dosyada saklar (dosya adını dosyanın gerçek adıyla değiştirin).
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
with open(dosyaadi, 'w') as f:
json.dump(d, f)
Bir dosyadan veri alma
Aşağıdaki kod parçacığı JSON kodlu bir dosyayı açar (dosya adını dosyanın gerçek adıyla değiştirin) ve dosyada depolanan nesneyi döndürür.
import json
with open(dosyaadi, 'r') as f:
d = json.load(f)
JSON çıktısını biçimlendirme
Diyelim ki elimizde aşağıdaki veriler var:
>>> data = {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Bunu sadece JSON olarak dökmek burada özel bir şey yapmaz:
>>> print(json.dumps(data)) {"cats": [{"name": "Tubbs", "color": "white"}, {"name": "Pepper", "color": "black"}]}
Daha güzel çıktı almak için girintiyi ayarlama
Eğer güzel bir çıktı istiyorsak, bir girinti boyutu ayarlayabiliriz:
>>> print(json.dumps(data, indent=2))
{
"cats": [{
"cats": [
{
“name”: “Tubbs”,
“color”: “white”
},
{
“name”: “Pepper”,
“color”: “black”
}
]
}
Tutarlı çıktı elde etmek için anahtarları alfabetik olarak sıralama
Varsayılan olarak çıktıdaki anahtarların sırası tanımsızdır. Her zaman aynı çıktıyı aldığımızdan emin olmak için bunları alfabetik sırayla alabiliriz:
>>> print(json.dumps(data, sort_keys=True))
{"cats": [{"color": "white", "name": "Tubbs"}, {"color": "black", "name": "Pepper"}]}
Kompakt çıktı elde etmek için boşluklardan kurtulma
Gereksiz boşluklardan kurtulmak isteyebiliriz, bunu da varsayılan ‘, ‘ ve ‘: ‘ ayırıcı dizelerinden farklı ayırıcı dizeleri ayarlayarak yapabiliriz:
>>>print(json.dumps(data, separators=(',', ':'))) {"cats":[{"name":"Tubbs","color":"white"},{"name":"Pepper","color":"black"}]}
JSON çıktısını güzel yazdırmak için komut satırından json.tool’u çağırma
“foo.json” gibi bir JSON dosyası verildiğinde:
{"foo": {"bar": {"baz": 1}}}
modülü doğrudan komut satırından çağırarak (dosya adını argüman olarak geçerek) güzel bir şekilde yazdırabiliriz:
$ python -m json.tool foo.json
{
"foo": {
"bar": {
"baz": 1
}
}
}
Modül ayrıca STDOUT’tan girdi alacaktır, bu nedenle (Bash’te) eşit şekilde yapabiliriz:
$ cat foo.json | python -m json.tool
JSON’dan Python dict oluşturma
import json
s = '{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}'
json.loads(s)
Yukarıdaki kod parçacığı aşağıdakileri döndürecektir:
{u'alice': 1, u'foo': u'bar', u'wonderland': [1, 2, 3]}
Python dict’ten JSON oluşturma
import json
d = {
'foo': 'bar',
'alice': 1,
'wonderland': [1, 2, 3]
}
json.dumps(d)
Yukarıdaki kod parçacığı aşağıdakileri döndürecektir:
'{"wonderland": [1, 2, 3], "foo": "bar", "alice": 1}
JSON özel nesneleri kodlama
Eğer aşağıdakileri denersek:
import json
from datetime import datetime
data = {'datetime': datetime(2016, 9, 26, 4, 44, 0)}
print(json.dumps(data))
TypeError: datetime.datetime(2016, 9, 26, 4, 44) is not JSON serializable şeklinde bir hata alıyoruz.
Datetime nesnesini düzgün bir şekilde serileştirebilmek için, onu nasıl dönüştüreceğimize dair özel kod yazmamız gerekir:
class DatetimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
try:
return obj.isoformat()
except AttributeError:
# obj'nin isoformat yöntemi yoktur; bırakın bunu yerleşik JSON kodlayıcı halletsin
return super(DatetimeJSONEncoder, self).default(obj)
ve sonra json.dumps yerine bu kodlayıcı sınıfını kullanın:
encoder = DatetimeJSONEncoder()
print(encoder.encode(data))
# prints {"datetime": "2016-09-26T04:44:00"}
load vs loads dump vs dumps
json modülü, hem unicode dizeleri okumak ve yazmak hem de dosyaları okumak ve yazmak için işlevler içerir. Bunlar, işlev adındaki sondaki s ile ayırt edilir. Bu örneklerde bir StringIO nesnesi kullandık, ancak aynı işlevler herhangi bir dosya benzeri nesne için de geçerli olacaktır.
Burada dize tabanlı fonksiyonları kullanırız:
import json
data = {u"foo": u"bar", u"baz": []}
json_string = json.dumps(data)
# u'{"foo": "bar", "baz": []}'
json.loads(json_string)
# {u"foo": u"bar", u"baz": []}
Ve burada dosya tabanlı fonksiyonları kullanıyoruz:
import json
from io import StringIO
json_file = StringIO()
data = {u"foo": u"bar", u"baz": []}
json.dump(data, json_file)
json_file.seek(0) # Okumadan önce dosyanın başlangıcına geri dönün
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
json_file.seek(0) # Okumadan önce dosyanın başlangıcına geri dönün
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
Gördüğünüz gibi temel fark, json verilerini dökerken dönüş değerini yakalamak yerine dosya tanıtıcısını işleve aktarmanız gerektiğidir. Ayrıca, veri bozulmasını önlemek için okumadan veya yazmadan önce dosyanın başlangıcını aramanız gerektiğini de belirtmek gerekir. Bir dosya açılırken imleç 0 konumuna yerleştirilir, bu nedenle aşağıdaki de çalışacaktır:
import json
json_file_path = './data.json'
data = {u"foo": u"bar", u"baz": []}
with open(json_file_path, 'w') as json_file:
json.dump(data, json_file)
with open(json_file_path) as json_file:
json_file_content = json_file.read()
# u'{"foo": "bar", "baz": []}'
with open(json_file_path) as json_file:
json.load(json_file)
# {u"foo": u"bar", u"baz": []}
Json verileriyle başa çıkmanın her iki yoluna da sahip olmak, json üzerine inşa edilen formatlarla deyimsel ve verimli bir şekilde çalışmanıza olanak tanır – pyspark’ın json-per-line gibi:
# bir dosyadan yükleme
data = [json.loads(line) for line in open(file_path).splitlines()]
# bir dosyaya dökme
with open(file_path, 'w') as json_file:
for item in data:
json.dump(item, json_file)
json_file.write('\n')