8 puan yazan GN⁺ 2025-09-22 | 1 yorum | WhatsApp'ta paylaş
  • Sj.h, yaklaşık 150 satırdan oluşan ultra hafif bir JSON ayrıştırıcısıdır ve C99 tabanlı ortamlarda kullanılabilir
  • Sıfır bellek tahsisi ve asgari durum tutma gibi özelliklere sahiptir; hafif gömülü ortamlarda veya bağımlılıkların en aza indirilmesinde avantaj sağlar
  • Sayı ve string ayrıştırma için doğrudan işleme yaklaşımını benimser; böylece kullanıcı ilgili işlemleri dilediği gibi gerçekleştirebilir
  • Satır:sütun tabanlı hata mesajları desteği sayesinde debugging sırasında okunabilirlik ve konum tespiti yüksektir
  • Public domain yazılım olarak, herkesin özgürce kullanmasına, değiştirmesine ve dağıtmasına izin verilir

Proje tanıtımı

  • Sj.h, aşırı özellikler veya gereksiz bellek tahsisi olmadan, yalnızca asgari düzeyde kodla JSON ayrıştırma işlevi sunan bir C99 header dosyasıdır
  • Tüm uygulama yaklaşık 150 satırdır; gömülü sistemler, araçlar veya harici kütüphane bağımlılıklarını azaltmak isteyen durumlar için uygundur

Başlıca özellikler

  • Sıfır bellek tahsisi (zero-allocations) ve asgari durum (minimal state) ile çalıştığı için bellek yükü çok düşüktür
  • Satır:sütun bilgisi içeren hata mesajları, ayrıştırma sırasında oluşan sorunların yerini kolayca belirlemeyi sağlar
  • Sayı ayrıştırma varsayılan olarak sunulmaz; kullanıcı strtod, atoi gibi istediği yöntemi kullanabilir
  • String ayrıştırma da doğrudan uygulanabilir; Unicode surrogate pair işleme gibi ihtiyaçlar isteğe göre eklenebilir
  • Tüm kaynak kodu public domain (Unlicense) olarak sunulur; bu sayede lisans kısıtları olmadan kullanılabilir ve değiştirilebilir

Kullanım örneği

  • JSON string’ini bir Rect yapısına ayrıştıran basit bir örnek sunuluyor
    char *json_text = "{ \"x\": 10, \"y\": 20, \"w\": 30, \"h\": 40 }";  
    typedef struct { int x, y, w, h; } Rect;  
    ...  
    
  • sj_Reader, sj_Value, sj_reader, sj_read, sj_iter_object gibi sade ve anlaşılır API’ler kullanır
  • Sayısal değer ayrıştırma veya anahtar-değer karşılaştırması kullanıcı tarafından doğrudan uygulanır (yerleşik olarak sunulmaz)
  • demo klasöründe çeşitli ek kullanım örnekleri bulunabilir

Lisans

  • Sj.h, herkesin hiçbir kısıtlama olmadan kullanabileceği bir public domain yazılımıdır
  • Ayrıntılar için LICENSE dosyasına bakılabilir

Diğer

  • Kod ve klasör yapısı basittir; ayrı bir yapılandırma veya build süreci olmadan doğrudan kullanılabilir
  • Bağımsızdır, dış bağımlılığı yoktur ve özellikle hafiflik ile kullanım kolaylığının önemli olduğu ortamlar için uygundur

1 yorum

 
GN⁺ 2025-09-22
Hacker News görüşleri
  • Bu yazarın işlerini sevmemin nedeni, çoğunun ANSI C ya da Lua ile yazılmış tek dosyalık kütüphaneler olması; kapsamına odaklanıyorlar, kullanımı kolay arayüzler ve harika dokümantasyon sunuyorlar, özgür yazılım lisansını da beğeniyorum. Bu proje dışında sevdiğim başka bazı işleri de var: log.c (basit bir C99 logging kütüphanesi), microui (çok küçük bir immediate-mode UI kütüphanesi), fe (gömülebilir küçük bir dil), microtar (hafif bir tar kütüphanesi), cembed (dosyaları C header'larına gömmek için araç), ini (.ini yapılandırma dosyaları için hafif kütüphane), json.lua (Lua için hafif JSON kütüphanesi), lite (Lua ile yazılmış hafif bir metin editörü), cmixer (oyunlar için taşınabilir audio mixer), uuid4 (C ile yazılmış küçük bir uuid4 kütüphanesi)
    • Ben C projelerinde log.c'yi her seferinde ekleyip kullanıyorum, yazarın bu kadar çok kütüphane yaptığını bilmiyordum. log.c gerçekten çok kolay kullanılıyor, tavsiye edebilirim
    • LOVE2D ile oyun yaparken Lume kütüphanesini kullanmıştım, yazara IRC sohbet odasında birkaç kez denk gelmiştim, hatta bir keresinde bir fikrine kötü demiştim ama şimdi tekrar bakınca iyi bir fikirmiş. https://github.com/rxi/lume bakmaya değer
    • Açık kaynak ama gerçek anlamda free software değil
  • Bu kütüphane şu satırlarda signed integer overflow kontrolü yapmıyor: L89, L149, L150. Belirli girdilerde undefined behavior oluşabilir
    • Bazı geliştiriciler basit tek-header C kütüphaneleri kültürünü seviyor, Tsoding gibi yayıncılar buna iyi bir örnek. Bu tür kütüphanelerin güvenlik ya da özellik zenginliğine odaklanmadığının farkındayım. Her proje çok sayıda müşteriye açık, kurumsal seviye yazılım olmak zorunda değil; bu yaklaşım da gayet olabilir
    • Tüm edge case'leri ele alan kütüphanelerin şişmesi hakkında iyi bir yazı var, bir de ilgili tartışma. Tüm hataları ele almaya çalışınca karmaşıklık çok hızlı artıyor; bazen de bu kütüphanenin sorumluluğu olmuyor
    • Seviye derinliği 2 milyardan fazlaysa ya da ikinci durumda satır sayısı 2 milyarı geçiyorsa UB oluşabilir. JS girdisini 1GB ile sınırlarsanız bunun üstünde zaten stack'in başka kısımlarında daha büyük sorunlar çıkacaktır. Eğer 2GB üstü JSON işleyecek olsaydım, kaynak koddaki tüm intleri 64 bite çevirirdim. Yine de girdi 2^64'ü aşarsa eninde sonunda patlar. Kodda int taşmalarını tek tek kontrol etmeyi düşünmüyorum
    • int 32 bit olduğu için ancak satır başına 2 milyar derinlikte iç içe yapı, 2 milyardan fazla satırlı dosya ya da 2 milyardan uzun tek satır olduğunda sorun çıkıyor
    • Bu kütüphane production'da kullanılacak gibi durmuyor
  • Bu kütüphane oldukça gevşek davranıyor. Bunun kötü bir şey olduğunu söyleyemem ama koduna bakmadan kullanacak kişiler için dikkat gerektiriyor. Kodun bu kadar küçük olmasının temel nedeni de bu. README'deki demo örneğine bakılırsa şöyle bir şeyde bile<br><code>{"x",10eee"y"22:5,{[:::,,}]"w"7"h"33<br>rect: { 10, 22, 7, 33 }</code> gibi çalışıyor
    • Parser genel olarak girdinin geçerli olduğunu varsayıyor. Doğrulama ise bu kütüphanenin kapsamadığı tamamen ayrı bir problem. Sonuçta bu kütüphane veri çıkarmaya yarıyor
    • Yani bu yüzden mi yanlış?
  • Genel olarak JSON parser kütüphanelerinin bir acı kara deliği olduğunu düşünüyorum. Her birinin hedeflediği yer farklı ve çoğu karmaşık soyutlamalarla dolu; çoğu zaman ikisi birden. Aslında belirli bir amaç için sadece gereken kısmı uygularsanız o kadar da zor bir problem değil
    • Modern JSON kütüphanelerinin ne kadar karmaşıklaştığı şaşırtıcı. Eskiden gerçekten basit olan nlohmann'ın C++ tek-header JSON kütüphanesi
  • 13 yaşında
  • bugün hâlâ aktif biçimde pull request merge ediliyor
  • 122 milyon unit test'i var Buna rağmen kendileri de en hızlısı olmadığını kabul ediyor; gerçekten hız gerekiyorsa simdjson öneriyorlar. Kendi JSON parser kütüphanenizi yazmayı hiç düşünmeseniz daha iyi; %90'ını 45 dakikada yazarsınız ama kalan %10 için on bin kişinin binlerce saat harcaması gerekir
    • Parsing JSON is a Minefield (2016) diye meşhur bir kaynak var: https://seriot.ch/projects/parsing_json.html
    • Bu kütüphane kadar tarafsız tasarlanmış olanı da nadir sanırım. Sadece key ve array item'larını sırayla döndürüyor, type ayrımını da string-slice ile veriyor
    • Bu proje zero-allocation ve minimum durum tutmayı öne çıkarıyor ama strings gibi en sık kullanılan tiplerde sonunda yine allocation gerekiyor. Benim problemim için oldukça farklı bir alternatif
    • S-Expressions'ın hâlâ sevilmesini umuyorum
  • İlginç ama bu kütüphanenin conformance test'lerden ne kadar geçtiğini merak ediyorum: https://github.com/nst/JSONTestSuite
    • Doğrulama açısından bu kütüphane pek katı görünmüyor; örneğin object ya da array'i ] veya } ile kapatmayı da kabul ediyor, \v karakterini de whitespace sayıyor, yani standarttan daha gevşek. Bunu daha çok "geçerli JSON için veri çıkarıcı" gibi görmek gerek. Ama string ya da number parser'ını da kendiniz yazmanız uğraştırıcı olabilir, özellikle üretici tarafla JSON gramerinin alt kümesi konusunda anlaşmanız gerekiyorsa
    • Gerçek implementasyonlara dayalı conformance test'ler üretmek gerçekten faydalı olabilir. Belirli bir parsing kütüphanesinin davranışıyla birebir eşleşen alt küme/üst küme test setleri üretmekten bahsediyorum. Böylece iki parser'ın aynı JSON'u farklı yorumlamasından doğan zafiyet risklerinden (ör. kimlik doğrulama atlatma) kaçınılabilir
    • Gerçekten soruyorum, iç içe object desteği var mı?
  • Biraz yarım parser gibi görünüyor; sayıları float ya da int'e çevirmiyor, yani o kısmı sizin ayrıca eklemeniz gerekecek gibi. Yine de etkileyici, kullanmayı düşünebilirim; sadece buna dikkat çekmek istedim
  • C99'un bu struct'ı varsayılan olarak 0 ile başlattığını mı söylediğini, yoksa = { 0 } kısmının mı eksik olduğunu merak ediyorum. İlgili kod'a bakınca r->depth başlatılmadan sj__discard_until döngüsünde tesadüfen depth ile eşit hale gelebilir gibi duruyor
    • r->depth burada zaten 0 olarak başlatılıyor, bkz. ilgili kod
  • Böyle bir kütüphanenin kullanım amacının ne olduğunu merak ediyorum; ortada zaten çok iyi JSON kütüphaneleri var gibi görünüyor, bu daha çok eğitsel bir araç mı?
    • Mevcut bir kod tabanına entegre etmesi kolay, boyut yükü küçük, heap allocation kullanmıyor, stdlib de kullanmıyor (stdbool.h ve stddef.h sadece type tanımları için dahil ediliyor), C++ template numaraları yok ve API sezgisel. Tüm bu koşulları aynı anda sağlayan C kütüphaneleri gerçekten çok az; C++ tarafında daha da az
    • Ek yük ve allocation olmadan parse etmesi cazip. Büyük JSON dump'larından (ör. Wikidata dump'ları) belirli özellikleri çekmek istediğinizde faydalı olabilir
    • Gömülü CPU üzerinde doğrudan kullanılabilir, hatta artık vape gibi cihazlarda bile API sunucusu çalıştırmak mümkün olabilir
    • Kod küçük olduğu için güvenliğin sıkı olduğu projelerde incelenmesi kolay, lisans uyumluluğu da çok basit (bildirim metni gerekmiyor)
    • Yeni başlayanlar için referans ya da basit parsing yapmak isteyenler için iyi bir kod tabanı olabilir. İşlemcisi kısıtlı küçük hobi projelerinde küçük bir kod ayak izi gerektiğinde işe yarar. Yine de böyle bir durumda muhtemelen TOML gibi bir dosya formatını tercih ederdim
  • Güzelmiş! Bir dahaki sefere C ile JSON parser gerekirse buna bakmayı düşünürüm. Ben yıllardır cJSON'u (https://github.com/DaveGamble/cJSON) sorunsuz kullandım. Ondan önce wjelement'i (https://github.com/netmail-open/wjelement) kullanıyordum ama bazı sorunlar nedeniyle sonunda değiştirdim (nedenlerini artık hatırlamıyorum)
  • Buna parser demek biraz zorlama gibi geliyor; genel olarak lexer'a daha yakın görünüyor