Home » U++ Library support » U++ Core » Jsonize problems with maps
Jsonize problems with maps [message #36002] |
Wed, 18 April 2012 09:11  |
Mindtraveller
Messages: 917 Registered: August 2007 Location: Russia, Moscow rgn.
|
Experienced Contributor |

|
|
There's a problem with maps jsonization.
Small example:#include <Core/Core.h>
using namespace Upp;
struct TestStruct
{
VectorMap<String,String> map;
void Jsonize(JsonIO &json)
{
json("map",map); //compile error!
}
};
CONSOLE_APP_MAIN
{
StoreAsJson(TestStruct());
}
Actually, I found 2 problems with jsonizing the Maps.
1) It doesn't actually compile (strange!)
2) Even if it compiled, json representation of such map is not optimal. IMO there must be special version for maps with string keys. It will make possible using native json way for representing such maps:
{ "key1":value1, "key2":value2, ... }
[Updated on: Wed, 18 April 2012 09:15] Report message to a moderator
|
|
|
|
|
|
Re: Jsonize problems with maps [message #36009 is a reply to message #36008] |
Thu, 19 April 2012 01:03   |
Mindtraveller
Messages: 917 Registered: August 2007 Location: Russia, Moscow rgn.
|
Experienced Contributor |

|
|
First, I had to implement two member functions of ValueMap class, which were declared in Documantation but were actually absent: const Value& GetKey(int i) const { return data->key[i]; }
const Value& GetValue(int i) const { return data->value[i]; }
So, here is the patch:template <class T, class K, class V>
void JsonizeStringMap(JsonIO& io, T& map)
{
if(io.IsLoading()) {
map.Clear();
const ValueMap& va = io.Get();
map.Reserve(va.GetCount());
for(int i = 0; i < va.GetCount(); i++) {
Value vv = va[i];
K key;
V value;
LoadFromJsonValue(key, va.GetKey(i));
LoadFromJsonValue(value, va.GetValue(i));
map.Add(key, value);
}
}
else {
Index<Value> index;
Vector<Value> values;
index .Reserve(map.GetCount());
values.Reserve(map.GetCount());
for (int i=0; i<map.GetCount(); ++i)
{
index .Add(StoreAsJsonValue(map.GetKey(i)));
values.Add(StoreAsJsonValue(map[i]));
}
ValueMap vm(index, values);
io.Set(vm);
}
}
template <class K, class V, class H>
void Jsonize(JsonIO& io, VectorMap<K, V, H>& map, bool)
{
JsonizeStringMap<VectorMap<K, V, H>, K, V>(io, map);
}
template <class K, class V, class H>
void Jsonize(JsonIO& io, ArrayMap<K, V, H>& map, bool)
{
JsonizeStringMap<ArrayMap<K, V, H>, K, V>(io, map);
}
Here is simple demo:#include <Core/Core.h>
using namespace Upp;
struct TestStruct
{
struct TestV : Moveable<TestV>
{
int a;
int b;
String ToString() const
{
return Format("a=%d, b=%d", a,b);
}
void Jsonize(JsonIO &json)
{
json
("a", a)
("b", b)
;
}
};
void Add()
{
TestV v;
v.a = Random(100);
v.b = Random(100);
map.AddPick(FormatIntHex(Random() ^ (int) GetTickCount()), v);
}
void Jsonize(JsonIO &json)
{
//Upp::Jsonize(json,map); // <- default
::Jsonize(json,map,true); // <- string map
}
VectorMap<String,TestV> map;
};
CONSOLE_APP_MAIN
{
TestStruct test, test2;
test.Add();
test.Add();
LoadFromJson(test2, StoreAsJson(test));
Cout() << StoreAsJson(test) << "\n============================\n" << StoreAsJson(test2) << "\n\n";
}
I'm not quite shure about efficiency of my implementation, but tried to comply Mirek's code as much as possible.
P.S. It would be good to have a mechanizm for "pretty" serialization. Possible interface could be: StoreAsJson(const T&, bool pretty = false). Is it possible to implement? Should I make a patch for it?
This will make possible storing program configuration in JSON format, not in XML. Which must be much more efficient and understandable.
[Updated on: Thu, 19 April 2012 01:08] Report message to a moderator
|
|
|
Re: Jsonize problems with maps [message #36011 is a reply to message #36009] |
Thu, 19 April 2012 09:20   |
 |
mirek
Messages: 14255 Registered: November 2005
|
Ultimate Member |
|
|
Mindtraveller wrote on Wed, 18 April 2012 19:03 | First, I had to implement two member functions of ValueMap class, which were declared in Documantation but were actually absent: const Value& GetKey(int i) const { return data->key[i]; }
const Value& GetValue(int i) const { return data->value[i]; }
|
Just for explanation:
They are not present in "legacy" Value implementation. Documentation is about new "SVO Value".
I still did not had balls to finally switch SVO Value as default (it was delayed as I have found a subtle bug a month ago)... but it is definitely coming before the end of May.
So, here is the patch:template <class T, class K, class V>
void JsonizeStringMap(JsonIO& io, T& map)
{
if(io.IsLoading()) {
map.Clear();
const ValueMap& va = io.Get();
map.Reserve(va.GetCount());
for(int i = 0; i < va.GetCount(); i++) {
Value vv = va[i];
K key;
V value;
LoadFromJsonValue(key, va.GetKey(i));
LoadFromJsonValue(value, va.GetValue(i));
map.Add(key, value);
}
}
else {
Index<Value> index;
Vector<Value> values;
index .Reserve(map.GetCount());
values.Reserve(map.GetCount());
for (int i=0; i<map.GetCount(); ++i)
{
index .Add(StoreAsJsonValue(map.GetKey(i)));
values.Add(StoreAsJsonValue(map[i]));
}
ValueMap vm(index, values);
io.Set(vm);
}
}
template <class K, class V, class H>
void Jsonize(JsonIO& io, VectorMap<K, V, H>& map, bool)
{
JsonizeStringMap<VectorMap<K, V, H>, K, V>(io, map);
}
template <class K, class V, class H>
void Jsonize(JsonIO& io, ArrayMap<K, V, H>& map, bool)
{
JsonizeStringMap<ArrayMap<K, V, H>, K, V>(io, map);
}
Here is simple demo:#include <Core/Core.h>
using namespace Upp;
struct TestStruct
{
struct TestV : Moveable<TestV>
{
int a;
int b;
String ToString() const
{
return Format("a=%d, b=%d", a,b);
}
void Jsonize(JsonIO &json)
{
json
("a", a)
("b", b)
;
}
};
void Add()
{
TestV v;
v.a = Random(100);
v.b = Random(100);
map.AddPick(FormatIntHex(Random() ^ (int) GetTickCount()), v);
}
void Jsonize(JsonIO &json)
{
//Upp::Jsonize(json,map); // <- default
::Jsonize(json,map,true); // <- string map
}
VectorMap<String,TestV> map;
};
CONSOLE_APP_MAIN
{
TestStruct test, test2;
test.Add();
test.Add();
LoadFromJson(test2, StoreAsJson(test));
Cout() << StoreAsJson(test) << "\n============================\n" << StoreAsJson(test2) << "\n\n";
}
[/quote]
Applied, only I do not really see the point of Jsonize with another bool parameter, that is why I have renamed it to StringMap. Thanks!
Mirek
|
|
|
|
|
Goto Forum:
Current Time: Tue Apr 29 09:48:02 CEST 2025
Total time taken to generate the page: 0.00766 seconds
|