Code Monkey home page Code Monkey logo

ston's Introduction

STON - Smalltalk Object Notation

CI

A lightweight text-based, human-readable data interchange format for class-based object-oriented languages like Smalltalk. It can be used to serialize domain level objects, either for persistency or network transport. As its name suggests, it is based on JSON (Javascript Object Notation). It adds symbols as a primitive value, class tags for object values and references. Implementations for Pharo Smalltalk, Squeak and Gemstone Smalltalk are available.

Installation

Metacello new
	baseline: 'Ston';
	repository: 'github://svenvc/ston/repository';
	load

Documentation

The original Smalltalk Object Notation paper

The Pharo Enterprise book STON chapter

The most formal description is The STON Specification

Sven Van Caekenberghe MIT Licensed

Dependency

Add the following code to your Metacello baseline or configuration

spec 
   baseline: 'Ston' 
   with: [ spec repository: 'github://svenvc/ston/repository' ]

ston's People

Contributors

astares avatar dalehenrich avatar demarey avatar ducasse avatar fniephaus avatar guillep avatar idisposable avatar jecisc avatar juliendelplanque avatar noha avatar svenvc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ston's Issues

Error parsing the empty symbol

Hello Sven,

I found that:

STON fromString: (STON toString: '' asSymbol)

raises a parsing error.

I guess #'' is a valid symbol so it should be supported by Ston... What do you think?

Thanks in advance,
Martín

STON incorrectly converts instances of Text

Text is a subclass of ArrayedColllection and STON uses encodeList: to encode the Text, but Text doesn't really take advantage of is array-ness, the real action for Text is in it's string and and runs instance variables .... the implication here is that even variable subclasses can have instance variables in addition to the indexable portion...

STON is not cycle-proof

I have run into some object graphs that end up in infinite loops during deserialization.

I haven't completely characterized the actual graph (it's pretty complex), but it appears that there are several points in the graph that refer back to the one of the root objects ... at the end of the initial pass there are one or more unresolvedReferences and because the graph is self referential the traversal looking to replace the unresolved references never terminates ...

As I think about there are probably two separate self-referential paths ... one reference is resolved and then the second path is followed which leads to the first self unresolved reference (now resolved) and we're off to the races ...

Some tests fail on Squeak

The following tests fail on Squeak-trunk:

  • STONTests>>testRoomExitCycles (fails)
  • STONWriterTests>>testDictionaryWithComplexKeys (fails)
  • STON.Tests.STONReaderTests>>testUnknow (errors)

It'd be nice if STON was fully Squeak-compatible, because we are using STON in smalltalkCI.

Improve method comments

Hi sven

after losing some moment trying to output a dictionary, I felt that improving the comments of put:* would be good.

STON class >> put: aDictionary onStream: stream
	"Put aDictinoary into the argument, stream.
	Here is a typical scenario
	
	| wrt |
	wrt := (FileSystem workingDirectory / 'pillar.xxx') writeStream.
	STON 
		put: (Dictionary new at: #a put: 33; yourself)
		onStream: wrt.
	wrt close
	
	Notice the close of the stream that will flush the output in the file.
	"
	(self writer on: stream) nextPut: aDictionary

I can do a PR if needed.
S.

new FileTree version available

Sven...thought I'd let you know that there is newer version of FileTree available. the new version has the (necessary) feature of preserving the method timestamps, so now there is zero loss of information.

It also eliminates the one override in Monticello. Speaking of which . It is a bit of a sticky wicket to upgrade to a newer version of FileTree, because of this modification. I have found over time, that you have to:

  1. move MCMethodDefinition>= to a different category
  2. upgrade to new version FileTree
  3. manually edit (or use method version browser) to eliminate the true ifTrue:[true] code.

Bug writing instances of SmallDictionary

I started to play with STON and I found it very nice. However, my objects have SmallDictionary so it fails. I will take a look... Thanks!

Reproduce with:

| anObject |

anObject := SmallDictionary with: (1 -> 2) with: (3 -> 4).

String streamContents: [ :stream |
    STON writer 
            prettyPrint: true;
            on: stream;
            nextPut: anObject ].

---> 

'SmallDictionary [
    2,
    4
]'

STON incorrectly converts instances of Interval

Admittedly I have not updated to the latest version of STON, so if it this is fixed great!

Otherwise, it appears that STON does not handle Interval instances correctly as the following throws an error in Pharo1.4:

...Smalltalk
STON fromString: (STON toString: (3 to: 6))
...

Apparently STON turns an interval into a collection:
...Smalltalk
'Interval[3,4,5,6]'
...
which doesn't seem correct ...

Dale

Floating point numbers not materializing correctly

Some floats are have different values after materialization due to loss in precision when doing arithmetic operations in STONReader.
Some examples: 0.022999999999999854, 4.999999999999996, Float fmin.
This should not occur and all values must be exactly the same after serializing and materializing.

Avoid writing variables with nil as value?

Hi Sven,

I am writing a lot of Ring definitions. For example, a method Ring definition is written like this:

'RGMethodDefinition {
    #annotations : IdentityDictionary {
        #className : #Integer,
        #statusKey : #active,
        #isMetaSide : false
    },
    #name : #''bitAnd:'',
    #parent : nil,
    #protocol : nil,
    #sourceCode : nil,
    #stamp : nil,
    #package : nil
}'

(Generated with STON toStringPretty: (Integer >> #bitAnd:) asRingDefinition)

This is a design problem of Ring, clearly not STON's fault. But since nil is the default value for instance variables, I wonder if it doesn't make sense to avoid writing them. I mean, the result might be:

'RGMethodDefinition {
    #annotations : IdentityDictionary {
        #className : #Integer,
        #statusKey : #active,
        #isMetaSide : false
    },
    #name : #''bitAnd:''
}'

What do you think?

Maybe its a better solution if Ring does it by itself, hooking how its instances are written.

Cheers,
Martín

Special floating point values cause errors on materialization

Special Float values (Float nan, Float infinity, Float negativeInfinity) are serialized as (Float nan, Float infinity, Float infinity negated) respectively. This causes error when trying to materialize them.
The way they are written out is not compatible with STON spec. So perhaps it would be better to represent them as Float [ #nan ] and similar.

Instances of Color deserialized as instances of Dictionary when being referenced in the STON serialization file

Steps to reproduce the problem:

  • load latest version of STON in a Pharo 7.0.3 image
  • use the Pharo Settings browser to store the settings and the load them again
  • go to the system menu and hover over the menu items
    -> notice how all menu items are 'broken' (red with a yellow cross).

What happens?
The system setting #\'Shortcut Reminder\'#textColor is deserialized as an instance of Dictionary rather than Color. As a result, the morph rendering breaks because it expects an instance of Color to be used as textColor and not an instance of Dictionary.

It seems it only happens because the value is a reference:

	StoredSetting {
		#settingNodeIdentifier : '#\'Shortcut Reminder\'#textColor',
		#realValue : @76
	},

The stored object at index 76 is indeed a Dictionary because that value was stored rather than the result of Color class>>fromSton:. It seems that the Color instance should be stored in the reference dictionary when reading the file. In other words: the result of the invocation of fromSton: should be stored.

32-bit Unicode characters not encoded/decoded correctly

The following returns false:

| str |
  str := (Character codePoint: 144271) asString.
  (STON fromString: (STON toString: str)) = str

The codePoint is encoded in 5 hex digits, but the STON character decoder only reads 4 of the hex digits ...

For GemStone, my solution is to use UTF8 to encode the entire STON text. I don't bother to encode the individual characters as the UTF8 encoded string is guaranteed to be 8-bit ASCII.

I believe this is similar to JSON, since JSON declares that the the JSON text is UTF8 encoded.

With that said, I've taken pains to make sure that isolate my GemStone implementation from the original STON implemenation, since I needed to handle 32-bit Unicode strings and will be able to adapt to whichever approach you decide to take to resolve this issue.

Symbols containing non-byte characters are not correctly serialized

If a Symbol contains characters outside the byte character set, then they are not correctly serialized by STON.

Some examples in Pharo 7:

ston := String streamContents: [:s | STON put: #'€' onStream: s]. "#'€', should be '#''€'''"
STON fromString: ston. "STONReaderError: At character 1: unexpected input"

Or from outside the basic plane:

ston := String streamContents: [:s | STON put: (Character value: 16r1F42C) asSymbol onStream: s]. "'#🐬'"
STON fromString: ston.

The issue is in STONWriter>>isSimpleSymbol:, which effectively ignores characters with code points > 255:

STONWriter new isSimpleSymbol: (Character value: 16r1F42C) asSymbol "true"

Bug reading instances of Text

Hi,

This happens only when there is a repeated character. Reproduce with:

| aString |

aString := STON toString: 'hh' asText. 
" ---> 'Text[Character[''h''],@2]' "

STON fromString: aString.
  1. Get ByteString(Object)>>error:

I'm on Pharo 30780 and STON-Core-SvenVanCaekenberghe.47

Improve the definition of legal characters in class names

As remarked by @Rydier (Henrik Sperre Johansen) the definition of legal characters in class names is not well done.

STONWriter will write out any system class name, while STONReader has both an isClassStartChar: and isClassChar: that basically restrict class names to ASCII.

We need to figure out what would be the best way forward.

Note that there is no escaping mechanism in class names as there is for symbols.

Serializing & materializing a Bag with duplicate elements fails

The following variation on STONWriteReadTests>>#testCollections signals an error:

testCollections2
	| collections |
	collections := STON listClass withAll: {
		Bag withAll: { 1@2. 3@4. 1@2. 3@4. 1@2 } }.
	self serializeAndMaterialize: collections

STONReaderError: At character 37: 'Inconsistent reference resolution'

Tested with the version of STON as included in Pharo 7 (“Pharo-7.0.0+rc1.build.117.sha.65868b2ab36e77ebb1db5f750725205e92999116 (64 Bit)”).

[BUG] - Can not serialize Float infinity

Hello,

Description

I was trying to use STON in a personal project (Serialization of Bloc). And i found a bug.

severity: high

Reproduction

code to reproduce:

serialization := STON toString: Float infinity.

materialization := STON fromString: serialization.

current result:

STON fromString: serialization raise an exception but the bug occurs durring the serilization.

STON toString: Float infinity create a String : 'Float infinity'.

Because STON serialize this 'number' as a Class, it will try to materialize it as class. And the exception is raise.

Possible fix

I try to fix it quick by adding a custom method fromSton: in Float class

Float class >> fromSton: aStonReader

	aStonReader match: 'infinity' do: [ ^ self infinity ].
	^ self nan

BUT, it breaks the STONReference indexation.

Durring serialization := STON toString: Float infinity. the STONWriter doesn't have any reference in the variable named objects.

image

Durring materialize:= STON toString: Float infinity. with the custom fromSton:, the STONReader have the reference of a Float object.

image

This will create errors of indexation when resolving STONReference.

Maybe a solution ?

I have a suggestion to fix the issue.

We could make the Float infinity as constant (like a boolean true or false) when we serialize it.

It would look like something like this:

Float >> stonOn: stonWriter

	self isInfinite
		ifTrue: [ stonWriter writeInfinite ]
		ifFalse: [ stonWriter writeFloat: self asFloat ]
STONWriter >> writeInfinite

	writeStream << #infinite
STONReader >> parseConstantDo: block

	"Custom to include Float infinite"

	readStream peek = $t ifTrue: [ 
		^ self match: 'true' do: [ block value: true ] ].
	readStream peek = $f ifTrue: [ 
		^ self match: 'false' do: [ block value: false ] ].
	readStream peek = $i ifTrue: [ 
		self match: 'infinite' do: [ block value: Float infinity ] ].
	readStream peek = $n ifTrue: [ 
		readStream next.
		readStream peek = $i ifTrue: [ 
			self match: 'il' do: [ block value: nil ] ].
		readStream peek = $u ifTrue: [ 
			self match: 'ull' do: [ block value: nil ] ] ]

I don't know if it will work with the JSON serialization.

Other

pharo image : Pharo-11.0.0+build.346.sha.b6ce4527b4f4881d6c6b4f968f1d1348b783b7a2 (64 Bit)

Color values lose precision when serialized

There is unnecessary rounding of values in Color>>#stonOn: that causes Color instances to not be the same after serialize/materialize roundtrip.
However issue #34 must also be addressed for any Color instance to be truly equal to itself after roundtrip, because alpha is stored as a float.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.