Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen NewMember »

Arkadaşlar Merhaba;
Delphi Web Broker implementasyonu ile bir Rest Api geliştiriyorum.
Server tarafında tablo alanlarını Record olarak tutuyorum.Clientten gelen Json veriyide SynCommon (morMot) kütüphanesi ile bu recordlara atıyorum.
Ve recorda ulaştıktan sonra ise bu recordu UniQuery(Unidac) bileşeni ile veritabanına yazdırıyorum.
Aslında burda bir sorun yok.
Sorun sadeece Put(Update) yönteminde bir küçük açmazım var.

Açıklamaya çalışayım.

Diyelim ki Cari tablomda 20 adet alanım var.
Doğal olarak ta CariRecord tipimde de 20 Adet property var.

Olabilecek tüm hata senaryolarını v.s. server tarafında elimine etmek, front-end geliştiricisine pek hata yapma fırsatı vermek istemiyorum.

Diyelimki Front-End geliştiricisi Put metoduna Json veriyi gönderdi.
Ama Json veri içinde 20 Adet field Key ve Value yerine 18 adet gönderdi.

Bu durumda serverde

Kod: Tümünü seç

SynCommons.RecordLoadJSON(entity, RawUTF8(requestData),

     TypeInfo(TCari));
metodu ile Cari recorduna verileri aldığımda bu clientten eksik gelen 2 alan doğal olarak Record tipimde boş string olarak geliyor.

Ve ben update yaparsam ise aslında clientin göndermediği bu iki alana ait veri de değiştirilerek emptystring olarak update edilecek.

Şimdi diyebilirsiniz ki:
1-Clientten gelen Json verinin field sayısını kontrol et.Eğer recordun field sayısına eşit değil ise cliente hata mesajı dön.
Bunu yapmak istemiyorum.Şu yüzden client tarafında ki geliştirici de esnek ve özgür kalsın istiyorum.
Yada şöyle diyelim.Her operasyon için server tarafında ayrı ayrı metodlara boğulmaktansa tek bir metodla işi bitireyim.
Clientteki geliştirici de hangi alanları güncellemek istiyorsa o alanları göndereceği kendi methodlarını oluştursun.
Yada ne bileyim işte önce diyelim serverdekş metodda 20 alanın 15 ini güncellemeye açtıysak eğer yarın öbür gün 16. alanında client tarafında güncellenmesi gerektiği zaman
server tarafında sırf bu alan için extra bir kod değişikliğine ve dolayısıyla server güncellemesine ihtiyaç duymayalım.
Yada sadece bir Cari tablsu için birden fazla Put metodu yazmayalım.Bu örnek belki cari tablus için biraz mantıksız görünebilir ancak karmaşık processlerde kesinlikle buna ihtiyacım olacak.

2.Şöyle bir yapı kur diyebilirsiniz.

Kod: Tümünü seç

if  not  (entity.CariTanimi ='') then

      ds.FieldByName('caritanimi').AsString := entity.CariTanimi;
Ancak bu durumda da eğer client gerçekten bu alanın içini boşaltmak isterse yani "CariTanimi":"", şekllinde bir Json Key Value si göndermek isterse bu sefer yukarıdaki kod bu alanın update edilmesini engelleyecektir.

Aslında sonuç olarak yapmak istediğim olay şu.
Örnek ile açıklayayım.

Clientten gelen JSON verisinde diyelimki Cari tablosuna ait veriler var.
Ve bu Json verisinde 15 adet Key Value çifti var.

Ama benim Cari recordumda ise 20 adet Property var.
İşte burada Json veryi Deserialize ettiğimde ,
ben bu Jsonda gönderilmemiş olan 5 adet propertynin hangileri olduğunu bilebilmeliyim ki,
serverdeki Update metodunda bu 5 alana dokunmayayım.
Onlar üzerinde güncelleme yapmayayayım.


Belki Server tarafındaki Tabloları Record üzerinde değilde , Classlar üzerinde tutsam.(c# Entity Framework mantığında olduğu gibi) o zaman bu Cari nesnesine bu alan Null
olarak gelicek ve ben bu null durumundan bunu anlayabileceğim.

Veya bu null olma durumu Record tipte de olsa gene olucak.
Ancak ben bu deserialize işleminde bu eksik alanları Null yapabilme olayını başaramadım.

Biraz uzun oldu ama kusura bakmayın.
Siz olsanız nasıl bir çözüm bulurdunuz bu soruna.
Ne gibi bir yol önerirsiniz.
Yardım edecek arkadaşlara şimdiden çok teşekkür ederim.
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen ertank »

Merhaba,

Record tanımlarınız için Variant veri türünü deneyin. Null değer alabilir. Null değerlere işlem yapmazsınız. Null olmayan diğer değerleri veri türü kontrolünden geçirip işleme dahil edersiniz.
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen NewMember »

ertank yazdı: 27 Ağu 2021 04:57 Merhaba,

Record tanımlarınız için Variant veri türünü deneyin. Null değer alabilir. Null değerlere işlem yapmazsınız. Null olmayan diğer değerleri veri türü kontrolünden geçirip işleme dahil edersiniz.
Çok teşekkür ederim ilginize.

Daha önceden yine sizden yardım almıştım.Mormot kütüphanesini önermiştiniz.
Başarıyla kullanıyorum.

Deserialize işlemini aşağıdaki kod ile yapıyorum.

Kod: Tümünü seç

SynCommons.RecordLoadJSON(entity, RawUTF8(requestData),
      TypeInfo(TCari));
Aslında bu Recordumdaki tipleri Variant olarak denemiştim.Ama siz yazınca bir kez daha denedim ancak yine Json veriden gelmeyen Key Value çiftinde de Null olarak deserialize işlemi olmuyor.

Kod: Tümünü seç

   if  not  (entity.CariTanimi =Null) then
       begin
              //Bu Blok çalışıyor.Json Verisinde  CariTanimi Key Value çifti olmamasına rağmen
               ds.FieldByName('caritanimi').AsString := entity.CariTanimi;
       end
       else
       begin
         ShowMessage('CariTanimi Null Değer İçeriyor");
       end;
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen ertank »

NewMember yazdı: 27 Ağu 2021 05:16 Aslında bu Recordumdaki tipleri Variant olarak denemiştim.Ama siz yazınca bir kez daha denedim ancak yine Json veriden gelmeyen Key Value çiftinde de Null olarak deserialize işlemi olmuyor.
Bahsi geçen JSON verisini paylaşabilir misiniz?
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen NewMember »

Kod: Tümünü seç

{
  "KayitId": "22",
  "VergiNo": "222222",
  "Tel1": "S9I",
  "CariKodu": "U",
  "Tel2": "E61HJ",
  "Tel3": "OKCIM62084",
  "Fax": "(481) 887-0659",
  "Il": "HE084",
  "Ilce": "O8",
  "MahalleKoy": "78",
  "CaddeSokakNo": "6ZZ5JFAID896GR",
  "EMail": "AdelaAkers277example.com"
}

Record

Kod: Tümünü seç

unit Cari;

interface

type
  TCari = packed record
    KayitId:  Variant;
    CariTanimi: Variant;
    VergiNo: Variant;
    Tel1: Variant;
    CariKodu: Variant;
    Tel2: Variant;
    Tel3: Variant;
    Fax: Variant;
    Il: Variant;
    Ilce: Variant;
    MahalleKoy: Variant;
    CaddeSokakNo: Variant;
    EMail: Variant;
    YetkiliAdi: Variant;
    VergiDairesi: Variant;
    CariTipi: Variant;
    Aciklama: Variant;
    KayitTarihi: Variant;
    WebSitesi: Variant;
    IskontoOrani: Variant;
    CariGrup: Variant;
    Sil: Variant;
    Silen: Variant;
    SilmeNedeni: Variant;
    PersonelId: Variant;
    CariHesapKodu: Variant;
    UyariVersinmi: Variant;
    CariRiskAnaliz: Variant;
    Meslek: Variant;
    VadeGunu: Variant;
    SmsGitsinmi: Variant;
    EfaturaMukellefi: Variant;
    DogumTarihi: Variant;
    DogumGunuSmsGitmeTarihi: Variant;
  end;
implementation

end.
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen ertank »

Debug ile incelemenizde fayda var. De-Serialize yapıldığında NULL olması gerekir verdiğiniz bilgilere göre. Eğer olmuyor ise başka bir yerde değeri değiştiriliyor olabilir.

Sorunun kaynağı değil ancak, VarIsNull() fonksiyonu ile kontrol etmeniz daha doğru olacaktır. System.Variants ünitesini uses kısmına eklemeniz gerekecektir kullanabilmeniz için.
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen ertank »

Şimdi test ettiğimde Record içindeki Variant veri türlerinin Unassigned olarak kaldığını gördüm. Dolayısıyla kontrolü aşağıdaki şekilde yapmalısınız:

Kod: Tümünü seç

procedure TForm2.Button1Click(Sender: TObject);
var
  Cari: TCari;
  Json: RawUTF8;
begin
  Json := RawUTF8(Memo1.Text);
  if not SynCommons.RecordLoadJSON(Cari, Json, TypeInfo(TCari)) then
  begin
    ShowMessage('JSON çözümlenemedi');
    Exit();
  end;

  if VarIsEmpty(Cari.CariTanimi) then
    Memo2.Lines.Add('Cari Tanımı = Unassigned');
end;
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen ertank »

ertank yazdı: 27 Ağu 2021 06:30 Şimdi test ettiğimde Record içindeki Variant veri türlerinin Unassigned olarak kaldığını gördüm. Dolayısıyla kontrolü aşağıdaki şekilde yapmalısınız:

Kod: Tümünü seç

procedure TForm2.Button1Click(Sender: TObject);
var
  Cari: TCari;
  Json: RawUTF8;
begin
  Json := RawUTF8(Memo1.Text);
  if not SynCommons.RecordLoadJSON(Cari, Json, TypeInfo(TCari)) then
  begin
    ShowMessage('JSON çözümlenemedi');
    Exit();
  end;

  if VarIsEmpty(Cari.CariTanimi) then
    Memo2.Lines.Add('Cari Tanımı = Unassigned');

  if VarIsNull(Cari.CariTanimi) then
    Memo2.Lines.Add('Cari Tanımı = NULL');
end;
VarIsEmpty() = Unassigned kontrolü yapıyor.
VarIsNull() = NULL kontrolü yapıyor.

NULL değer Unassigned değildir. Unassigned değer ise NULL değildir.

Siz kendinize uygun yöntemi belirleyip ona göre işlem yapabilirsiniz.
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen NewMember »

ertank yazdı: 27 Ağu 2021 06:35
ertank yazdı: 27 Ağu 2021 06:30 Şimdi test ettiğimde Record içindeki Variant veri türlerinin Unassigned olarak kaldığını gördüm. Dolayısıyla kontrolü aşağıdaki şekilde yapmalısınız:

Kod: Tümünü seç

procedure TForm2.Button1Click(Sender: TObject);
var
  Cari: TCari;
  Json: RawUTF8;
begin
  Json := RawUTF8(Memo1.Text);
  if not SynCommons.RecordLoadJSON(Cari, Json, TypeInfo(TCari)) then
  begin
    ShowMessage('JSON çözümlenemedi');
    Exit();
  end;

  if VarIsEmpty(Cari.CariTanimi) then
    Memo2.Lines.Add('Cari Tanımı = Unassigned');

  if VarIsNull(Cari.CariTanimi) then
    Memo2.Lines.Add('Cari Tanımı = NULL');
end;
VarIsEmpty() = Unassigned kontrolü yapıyor.
VarIsNull() = NULL kontrolü yapıyor.

NULL değer Unassigned değildir. Unassigned değer ise NULL değildir.

Siz kendinize uygun yöntemi belirleyip ona göre işlem yapabilirsiniz.
@ertank Öncelikle elimde olmayan sebeplerden dolayı ancak mesajlara bakabildim ve geç cevap yazdığım için özür dilerm.
Yardımlarınız için çok teşekkürler.

Söylediğiniz gibi yapınca yakaladım.
Yine de bilgi için buraya not düşelim.Belki başkalarınında ihtiyacı olur.

Aşağıdaki kod bloklarının hepsi Jsonda olmayan veriyi tespit etmeme yetti.

Kod: Tümünü seç

 if  entity.CariTanimi = UnAssigned  then
  if VarIsNull(entity.CariTanimi) then
  if VarIsEmpty(entity.CariTanimi) then
Ama yinede sizin söylediğiniz gibi bu VarIsnull ve VarIsempty metodları farklı olabilir.
Şu an için bende ikiside çalıştı.
Hatta sizin söylediğinizden esinlenerek Unassigned eşitlemesi bile çalıştı.
Tekrar teşekkürler.
İyi akşamlar.
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen NewMember »

Ekleme:
Tekrar denedim.

Eğer Recorddaki veri tipini string yapar isem VarIsnull ve VarIsEmpty yakalayamıyor. Unassigned ise yakalıyor.
Debug yaptığımda CariTanimi alani Unassigned görünmemesine rağmen '' şekliinde boş string görünmesine rağmen UnAssigned olarak yakalıyor.
(Not:Debugta eğer Recorddaki CariTanimi alanını Variant yaptıysam Unassigned olarak gösteriyor.String yaptıysam empty string şeklinde '' gibi göstermesine rağmen UnAssigned değerini alıuor.)
Yani Unassigned her iki durumda da yakalıyor.
ertank
Kıdemli Üye
Mesajlar: 1650
Kayıt: 12 Eyl 2015 12:45

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen ertank »

Variant kullanmanız daha sağlıklı olur. Boş string değer gerçekten kayıt edilmek için gönderilebilir. Ancak değerin olmaması veya NULL olması şüpheye yer bırakmaz.

VarIsEmpty() sizin için Unassigned kontrolü yapar.
VarIsNull() sizin için NULL değer olup olmadığını kontrol eder.

VarIsEmpty() ile kontrol ediyorsanır ayrıca CariEntity.CariTanimi = Unassgined şeklinde bir kontrol gereksizdir.
Kullanıcı avatarı
NewMember
Üye
Mesajlar: 990
Kayıt: 29 Haz 2005 06:57
Konum: Bursa

Re: Json Veriyi Record Tipe Deserializede eksik değerlerin Null yapılabilmesi

Mesaj gönderen NewMember »

ertank yazdı: 28 Ağu 2021 11:22 Variant kullanmanız daha sağlıklı olur. Boş string değer gerçekten kayıt edilmek için gönderilebilir. Ancak değerin olmaması veya NULL olması şüpheye yer bırakmaz.
Haklıısnız.Sakin kafayla bir kaç test daha yaptım.
Variant ataması yapmazsak pek sağlıklı olmuyor.

Vardığım sonuç.
Record veri tiplerini Variant yapacağız.
En sağlıklı kontrol de şu şekild eçalıştı.

Kod: Tümünü seç

  if  not (entity.CariTanimi=UnAssigned) then
           ds.FieldByName('caritanimi').AsString := entity.CariTanimi;
Cevapla