ahausladen / JsonDataObjects

JSON parser for Delphi 2009 and newer
MIT License
413 stars 160 forks source link

(Proposed) Internally handle DateTime values as jdtDateTime #12

Closed kattunga closed 8 years ago

kattunga commented 9 years ago

I'm interested in implement a jdtDateTime type to handle of DateTime values in the same way that Float values are handled. This will let us to transparently handle DateTime values instead of manually convert or format them when needed. This also save memory because it will store a double value instead of 24 chars. Some examples of use could be:

procedure TForm2.Button2Click(Sender: TObject);
var
  doc: TJsonObject;
  variantvar: variant;
  datetimevar: TDateTime;
  stringvar: string;
begin
  doc := TJsonObject.Create;
  try

    // assign a datetime value and internally store as Double, with Typ = jdtDateTime
    doc['mydatetimevalue'] := now;
    doc.D['mydatetimevalue'] := now;

    // return value as TDateType
    variantvar := doc['mydatetimevalue'];
    variantvar := doc['mydatetimevalue'].DateTimeValue;
    variantvar := doc.D['mydatetimevalue'];

    // return value as TDateType
    datetimevar := doc['mydatetimevalue'];
    datetimevar := doc['mydatetimevalue'].DateTimeValue;
    datetimevar := doc.D['mydatetimevalue'];

    // cast to string to standard JsonFormat
    stringvar := doc['mydatetimevalue'];
    stringvar := doc['mydatetimevalue'].Value;

    // output dates as standard JSON format
    doc.ToJSON; // will output -> {"mydatetimevalue": "yyyy-mm-ddThh:mm:ss.zzzZ"}

  finally
    doc.Free;
  end;
end;

I think that this doesn't broke or change anything. But I want to hear your opinions before start to work. If you agree I will do it in my fork and then I'll put a pull request.

ahausladen commented 9 years ago

The only problem I see is when parsing the JSON string. The JSON parser only sees a string " "yyyy-mm-ddThh:mm:ss.zzzZ" but it doesn't know that it should store the data in the TDateTime field. So you only save memory if you create a JSON object but not if you load one. Making the parser aware of the date format would slow it down (how much, I don't know)

kattunga commented 9 years ago

Hi Andreas,

I'm using JsonDataObjects in a HttpServer that I develop to make Json responses from large Query datasets. Implementing jdtDateTime let me create the Json response as simple as:

...
  jsonArrayO[DataSet.RecNo-1][DataSet.Fields[i].FieldName] := DataSet.Fields[i].Value;
...

With less memory footprint than if I convert and store DateTime fields as strings.

My original idea was to not touch the parser. If you parse from string, dates should be stored as strings because there are no way to exactly know if the original value is a date or a string, you can guess it but you can't be sure. In this case you only lost the memory reduction but you can still handle DateTime data:

var
  datetimevar: TDateTime;
begin
  doc := TJsonBaseObject.FromJSON('{"mydatetimevalue": "yyyy-mm-ddThh:mm:ss.zzzZ"}');

  // return value as TDateType
  datetimevar := doc['mydatetimevalue'];
  datetimevar := doc['mydatetimevalue'].DateTimeValue;
  datetimevar := doc.D['mydatetimevalue'];
end;

But after I read your response I'm thinking that may be we can add a parameter in Parser to let the user decide it.

procedure FromJSON(S: PWideChar; Len: Integer = -1; AutoDetectDates: boolean = False);

If you like this idea, I prefer to create a new issue to implement this separately after the jdtDateTime data type.

Regards Christian

kattunga commented 8 years ago

Hi Andreas, did you take a look to my pull request? I have it in production since I post and it work perfect. I hope you can include in master branch.

Regards