2

I'm working on a wrapper for dropbox in delphi 2012. The problem I'm running into is deserializing the json responses. When I make the request for a list of folders and files in my account I get a response that looks something like this:

{
    "hash": "some_hash",
    "thumb_exists": false, 
    "bytes": 0,
    "path": "/", 
    "is_dir": true, 
    "size": "0 bytes", 
    "root": "dropbox", 
    "contents": 
    [
        {
            "revision": 11, 
            "rev": "b074cbcbb", 
            "thumb_exists": false, 
            "bytes": 0, 
            "modified": "Mon, 23 Apr 2012 19:19:27 +0000", 
            "path": "/Apps", 
            "is_dir": true, 
            "icon": "folder", 
            "root": "dropbox", 
            "size": "0 bytes"
        }, 
        {    
            "revision": 142, 
            "rev": "8e074cbcbb", 
            "thumb_exists": false, 
            "bytes": 0, 
            "modified": "Wed, 09 May 2012 22:55:44 +0000", 
            "path": "/code", 
            "is_dir": true, 
            "icon": "folder", 
            "root": "dropbox", 
            "size": "0 bytes"
        },
        {
            "revision": 7,
            "rev": "7074cbcbb", 
            "thumb_exists": false, 
            "bytes": 246000, 
            "modified": "Mon, 23 Apr 2012 18:40:51 +0000", 
            "client_mtime": "Mon, 23 Apr 2012 18:40:52 +0000", 
            "path": "/Getting Started.pdf", 
            "is_dir": false, 
            "icon": "page_white_acrobat", 
            "root": "dropbox", 
            "mime_type": "application/pdf", 
            "size": "240.2 KB"
        }
    ],
    "icon": "folder"
}

I would like to be able to parse that using a TJSONUnMarshal object, but it turns out that TJSONUnMarshal expects the json to look like this instead:

{
"type":"DropboxApiU.TFile",
"id":1,
"fields":
{
    "hash": "some_hash",
    "thumb_exists": false, 
    "bytes": 0,
    "path": "/", 
    "is_dir": true, 
    "size": "0 bytes", 
    "root": "dropbox", 
    "contents": 
    [
        {
            "type":"DropboxApiU.TFile",
            "id":1,
            "fields":
            {
                "revision": 11, 
                "rev": "b074cbcbb", 
                "thumb_exists": false, 
                "bytes": 0, 
                "modified": "Mon, 23 Apr 2012 19:19:27 +0000", 
                "path": "/Apps", 
                "is_dir": true, 
                "icon": "folder", 
                "root": "dropbox", 
                "size": "0 bytes"
            }
        },

I've looked at this page and thought it might be what I'm looking for, but it never really goes into how to use a TTypeObjectReverter (which I think is what I need to use) and I can't seem to find an example online.

What would be the best way to make this happen? I'm hoping I can just write a TTypeObjectReverter, or something similar, but I would need to see a sample to be able to wrap my head around that.

edit Here's a screenshot of the differences between the two. The red is not sent in the response from the dropbox server, but is expected by the unmarshaler.

Differences

nick
  • 2,833
  • 3
  • 34
  • 61
  • There is missing the end of a second file. Anyway except the JSON files would be nice to include also a screenshot from some differencing tool (it's friday and I'm so lazy to do it by myself :-) – TLama May 11 '12 at 22:06
  • 1
    @TLama I uploaded a screen shot, and the second one is missing the end because all the differences are shown in the first part and I was too lazy on this glorious friday to rebuild the entire request the way delphi was expecting it :) – nick May 11 '12 at 22:15

2 Answers2

4

You could use my SvSerializer class for this task. First, you'll need to define your class which you want to serialize/deserialize, e.g.:

TDropbox = class
  private
    FHash: string;
    Fthumb_exists: Boolean;
    Fbytes: Integer;
    Fpath: string;
    Fis_dir: Boolean;
    FSize: string;
    Froot: string;
    Fcontents: TArray<TContent>;
    Ficon: string;
  public
    [SvSerialize]
    property Hash: string read FHash write FHash;
    [SvSerialize]
    property thumb_exists: Boolean read Fthumb_exists write Fthumb_exists;
    [SvSerialize]
    property bytes: Integer read Fbytes write Fbytes;
    [SvSerialize]
    property path: string read Fpath write Fpath;
    [SvSerialize]
    property is_dir: Boolean read Fis_dir write Fis_dir;
    [SvSerialize]
    property size: string read FSize write FSize;
    [SvSerialize]
    property root: string read Froot write Froot;
    [SvSerialize]
    property contents: TArray<TContent> read Fcontents write Fcontents;
    [SvSerialize]
    property icon: string read Ficon write Ficon;
  end;

TContent = record
  private
    frevision: Integer;
    Frev: string;
    Fthumb_exists: Boolean;
    Fbytes: Integer;
    fmodified: string;
    fclient_mtime: string;
    fpath: string;
    fis_dir: Boolean;
    ficon: string;
    froot: string;
    fmime_type: string;
    fsize: string;
  public
    property revision: Integer read frevision write frevision;
    property rev: string read Frev write Frev;
    property thumb_exists: Boolean read Fthumb_exists write Fthumb_exists;
    property bytes: Integer read Fbytes write Fbytes;
    property modified: string read fmodified write fmodified;
    property client_mtime: string read fclient_mtime write fclient_mtime;
    property path: string read fpath write fpath;
    property is_dir: Boolean read fis_dir write fis_dir;
    property icon: string read ficon write ficon;
    property root: string read froot write froot;
    property mime_type: string read fmime_type write fmime_type;
    property size: string read fsize write fsize;
  end;

Then add TDropbox object's instance to serializer:

FSerializer := TSvSerializer.Create();
FDropboxFile := TDropbox.Create;
FSerializer.AddObject('', FDropboxFile);

And now you can serialize/deserialize this object through SvSerializer:

FSerializer.DeSerialize(mmo1.Lines.Text{your json string, stream or filename}, TEncoding.UTF8{if it is string you must specify the encoding});
//After this line your FDropBoxFile's properties are filled from your json string
Linas
  • 5,485
  • 1
  • 25
  • 35
  • New to Delphi, your class definition's use of property construct helped me solve a deserialization issue I was battling for quite sometime! – Santosh Aug 25 '14 at 14:06
2

May be you could try using Progdigy´s JSON Wrapper instead?

Luis Carrasco
  • 467
  • 3
  • 10