JSON .ToString problem

In my code I have something like this:

  dim dic as new Dictionary
  dic.Value("DocumentTitle") = DocWindow.mTitle
  dic.Value("Top") = DocWindow.top
  dic.Value("Left") = DocWindow.left
  dic.Value("Width") = DocWindow.width
  dic.Value("Height") = DocWindow.heigth
  dic.Value("BGcolor") = DocWindow.mBackgroundColor
  
  dim jData as JSONItem
  jData = dic
  
  dim Buffer as string
  Buffer = jData.ToString

Unfortunately this throughs an error on the line where I put the JSONdata into the Buffer string:

My guess is that something goes wrong when XOJO parses the a color value in the JSONitem.

In the FeedBack app I was told that it was not valid JSON. But on the provided link to the json page I couldn’t find the problem

Its invalid JSON

Probably dic.Value(“BGcolor”) = DocWindow.mBackgroundColor
which turns into
“BGColor” : &h00669900

The number is not a valid json number so you may need to convert it to a string with quotes OR strip off the &h
Or make sure the color gets put into the dictionary as an integer
dic.Value(“BGcolor”) = format(DocWindow.mBackgroundColor, “00000000”)

Looks like an hexadecimal value. Why should that be a problem?

its not legal json
Try it http://jsonlint.com
Type in { “BGColor” : &h00669900 }

In your code put a break point on the line

dim jData as JSONItem

Run your code and when it stops on that line look in the dictionary & see what value the key “BGColor” has
If it really is &h00669900 thats the problem

JSON is quite strict about what it does & does not accept & if you try to shove just any old values in it you get errors like you’re seeing

Attach some sample code from your project to the feedback report

Thanks. I see that JSON doesn’t like the &h… value

The thing is, I try to create some kind of Config-file class. I store a brought variety of properties in a dictionary:

Assuming data is a dictionary:

Sub Field(FieldName as String, Assigns v as Variant)
  if FieldName.Trim = "" then Return
  data.Value( FieldName.Trim ) = v
end sub

Function Field(FieldName as string)
  if FieldName.Trim = "" then Return ""
  if data.HasKey(FieldName.trim) then Return data.Value( FieldName.Trim )
End Function

This is basically how I set up my dictionary.
I was hoping that Xojo would do something with value types like COLOR, just like SQLite does with various types

You could convert the color to hex and store it as a string in the JSONItem. Then when you are converting back you take the string and convert it back to a color.

While it could maybe tell its a color when you create the json when you read it it would at best be an integer
So you need to do some handling one way or the other

This demonstrates the same issue you’re seeing

[code]
dim dic as new Dictionary
dic.Value(“BGcolor”) = &c00669900
dim jData as JSONItem
jData = dic

dim Buffer as string
Buffer = jData.ToString[/code]

And this code shows why

dim c as color = &c00669900 dim v as variant = c dim s as string = v.StringValue

The “string” representation of a color is &hxxxxxxxx
Even if it were &cxxxxxxxx it would still be invalid JSON

So you will have to do something to deal with this in your code

I have a better solution, I think.
Maybe it is better to store values in a pair , where the left value is the actual value, but than represented as integer in case of a type color, and the right value is the value type.

When retrieving the values back from the dictionary I can transform everything back to the values I need.

The code below is not yet tested. But I think a night of good sleep did help to get some inspiration. Haha :wink:
Right now it only sets the value for the the color type. Maybe I should do this for other values as well. Will try this later today.

[code]
Dim p as Pair

select case value.type
case variant.color
p.left = value.type
p.right = integer( value )
case else
p.left = -1
p.right = value
end case

dic.value(“PropertyName”) = p[/code]

I’ve solved this last week for dates, which also make toString puke. A similar approach might do for colors:

[code] dim PrefsDictionary as Dictionary = getAllPrefsAsDictionary

'replace dates with sql datestring because they cause a JSONException
for currentPref as Integer = 0 to PrefsDictionary.Count - 1
dim theValue as Variant = PrefsDictionary.Value(PrefsDictionary.Key(currentPref))
if theValue isA Date then
PrefsDictionary.Value(PrefsDictionary.Key(currentPref)) = theValue.DateValue.SQLDate
end if
next
dim theJson as JSONItem = PrefsDictionary
try
Return theJson.ToString
Catch JSONException
'ignore
end try[/code]

That reminds me that I also save a color value I think … somewhere.

@Beatrix Willius , (JSON sounds similar to the word awesome… if you pronounce it fast enough :wink:
And fortunately there are always workarounds for small little problems. Although I would have loved to see that there are no problems with data types like Date and Color.

That makes me wonder: what if a PreferenceProperty is a structure, an array of colors (or dates) or a dictionary. But so far I have no need to store those kind of values in a JSON data stream.

Sometimes it would make it easier to dump all the preference data in a SQLite database:

rs.field("PropName").stringvalue = PropertyName rs.field("PropValue").variant = value
But setting up a DB like this, from scratch, is more of a hassle than using a JSON stream in a Binary File. Besides, all preferences would be pulled in a dictionary anyway. And I think pulling data from a database everytime I need a value will significantly slow down the application.

Also, if data needs to be stored on a server, JSON is the answer to package things up nicely. A JSON stream is encrypt-able. That is useful if you store data like passwords and such.
I use the BlowFish module for that.

Maybe it is a good idea to build a nice opensource class to deal with preferences. but than a class that is easy to use. I have seen a few around. And they were not as easy as one might hope.