ahausladen / JsonDataObjects

JSON parser for Delphi 2009 and newer
MIT License
414 stars 159 forks source link

LoadFromStream Fails #7

Closed chmichael closed 9 years ago

chmichael commented 9 years ago

Hello, The SaveFromStream works, but LoadFromStream raise an exception.

ahausladen commented 9 years ago

What Delphi version? What is the exception and where is the location of the exception?

chmichael commented 9 years ago

XE7up1 - the error: unexpected end of file were "{" was expected but found "[".

procedure TJsonReader.AcceptFailed(TokenKind: TJsonTokenKind); begin if FLook.Kind = jtkEof then raise EJsonParserException.CreateResFmt(@RsUnexpectedEndOfFile, [JsonTokenKindToStr[TokenKind]]); raise EJsonParserException.CreateResFmt(@RsUnexpectedToken, [JsonTokenKindToStr[TokenKind], JsonTokenKindToStr[FLook.Kind]]); end;

ahausladen commented 9 years ago

Do you have an example JSON string? My JSON strings all work.

chmichael commented 9 years ago

Just use JsonDataObjectsTest and check only LoadFromStream test.

ahausladen commented 9 years ago

No problem with XE7Up1 and XE8Up1 and the TestLoadFromStream test case on my system. And I don't have local changes in the working copy.

chmichael commented 9 years ago

Here is a sample project: http://we.tl/P0azSt6nOm

ahausladen commented 9 years ago

In your sample project the memory stream is at the end of the stream. So there is nothing to read for LoadFromStream and that's why the EOF exception is thrown.

A "vStringStream.Position := 0;" helps.

But this only gives me "Unexpected end of file where "{" was expected.". You got unexpected end of file were "{" was expected but found "[".. So either the stream that you use in your actual application is at a different position than "end of stream"/"begin of stream" or something else is wrong.

chmichael commented 9 years ago

Ok that was what i forgot to put on the sample ...

The actual problem is that i parse the record into JsonObject (as you can see in my sample) and the i'm trying to save the Json into CLOB field. (CLOB Field: http://www.elevatesoft.com/manual?action=viewtopic&id=edb2sql&topic=String_Types)

with this line: FieldByName('Data').AsString := vJsonObject.ToJSON;

This save fine the JSON to the Clob field. (IOW, I can see the JSON text from the DB)

Now the problem is when i try to load it ...

var vStream: TMemoryStream; FJsonObject: TJsonObject; begin vStream := TMemoryStream.Create; FJsonObject := TJsonObject.Create;

//btw, this doesn't work -> FSuperObject.Parse(FExaminationQuery.FieldByName('Data').AsString);

TBlobField(FExaminationQuery.FieldByName('Data')).SaveToStream(vStream); vStream.Position := 0;

FJsonObject.LoadFromStream(vStream);

throughs the below error:

Expected "," but found value procedure TJsonReader.AcceptFailed(TokenKind: TJsonTokenKind);

now, if i save the clob data into a file, from notepad++ i can read it but it has not character encoding checked on the notepad++. If i set it to UTF8, save the file and load it from JsonObject it parse it correctly !!!

So i the problem was the encoding !!!

Load/Parse it as Unicode encoding solved the problem: FJsonObject.LoadFromStream(vStream, TEncoding.Unicode); IOW, it parse it from the Database correctly.

So, the LoadFromStream detects a Unicode text incorrectly as UTF8 or i must set it my self ?

Thank you for your help !!

In case you wanted I saved the Json into a file -> http://we.tl/U9KEti4soc

vStream := TMemoryStream.Create; vStream.LoadFromFile('c:\test\test.json'); vStream.Position := 0;

FJsonObject.LoadFromStream(vStream); // fails FJsonObject.LoadFromStream(vStream, TEncoding.Unicode); //works

ahausladen commented 9 years ago

procedure LoadFromStream(Stream: TStream; Encoding: TEncoding = nil; Utf8WithoutBOM: Boolean = True);

If no encoding is specified it assumes UTF-8 (Utf8WithoutBOM=True) or ANSI (Utf8WithoutBOM=False). There is no way to identify UTF-16 without a BOM. So you have to tell JsonDataObject that your stream is TEncoding.Unicode.

chmichael commented 9 years ago

Got it :) Thank you a lot !!