1 /* Copyright 2014, Uwe L. Korn <uwelk@xhochy.com>
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in all
11  * copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19  * SOFTWARE.
20  */
21 
22 #include "Json.h"
23 
24 // Qt version specific includes
25 #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
26 #include <QJsonDocument>
27 #include <QMetaProperty>
28 #include <QVariantHash>
29 #else
30 #include <qjson/parser.h>
31 #include <qjson/qobjecthelper.h>
32 #include <qjson/serializer.h>
33 #endif
34 
35 namespace QJsonWrapper
36 {
37 
38   QVariantMap
qobject2qvariant(const QObject * object)39   qobject2qvariant( const QObject *object )
40   {
41 #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
42     QVariantMap map;
43     if ( !object )
44     {
45       return map;
46     }
47 
48     const QMetaObject *metaObject = object->metaObject();
49     for ( int i = 0; i < metaObject->propertyCount(); ++i )
50     {
51       QMetaProperty metaproperty = metaObject->property( i );
52       if ( metaproperty.isReadable() )
53       {
54         map[ QLatin1String( metaproperty.name() ) ] = object->property( metaproperty.name() );
55       }
56     }
57     return map;
58 #else
59     return QJson::QObjectHelper::qobject2qvariant( object );
60 #endif
61   }
62 
63 
64   void
qvariant2qobject(const QVariantMap & variant,QObject * object)65   qvariant2qobject( const QVariantMap &variant, QObject *object )
66   {
67 #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
68     for ( QVariantMap::const_iterator iter = variant.begin(); iter != variant.end(); ++iter )
69     {
70       QVariant property = object->property( iter.key().toLatin1() );
71       Q_ASSERT( property.isValid() );
72       if ( property.isValid() )
73       {
74         QVariant value = iter.value();
75         if ( value.canConvert( property.type() ) )
76         {
77           value.convert( property.type() );
78           object->setProperty( iter.key().toLatin1(), value );
79         }
80         else if ( QString( QLatin1String( "QVariant" ) ).compare( QLatin1String( property.typeName() ) ) == 0 )
81         {
82           object->setProperty( iter.key().toLatin1(), value );
83         }
84       }
85     }
86 #else
87     QJson::QObjectHelper::qvariant2qobject( variant, object );
88 #endif
89   }
90 
91 
92   QVariant
parseJson(const QByteArray & jsonData,bool * ok,QByteArray * errorString)93   parseJson( const QByteArray &jsonData, bool *ok, QByteArray *errorString )
94   {
95 #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
96     QJsonParseError error;
97     QJsonDocument doc = QJsonDocument::fromJson( jsonData, &error );
98     if ( ok )
99     {
100       *ok = ( error.error == QJsonParseError::NoError );
101     }
102     if ( errorString && !ok )
103     {
104       *errorString = error.errorString().toUtf8();
105     }
106     return doc.toVariant();
107 #else
108     QJson::Parser p;
109     QVariant variant = p.parse( jsonData, ok );
110     if ( errorString && !ok )
111     {
112       *errorString = p.errorString().toUtf8();
113     }
114     return variant;
115 #endif
116   }
117 
118 
119   QByteArray
toJson(const QVariant & variant,bool * ok,QByteArray * errorString,bool indented)120   toJson( const QVariant &variant, bool *ok, QByteArray *errorString, bool indented )
121   {
122 #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
123     QVariant _variant = variant;
124     if ( variant.type() == QVariant::Hash )
125     {
126       // QJsonDocument cannot deal with QVariantHash, so convert.
127       const QVariantHash hash = variant.toHash();
128       QVariantMap map;
129       QHashIterator<QString, QVariant> it( hash );
130       while ( it.hasNext() )
131       {
132         it.next();
133         map.insert( it.key(), it.value() );
134       }
135       _variant = map;
136     }
137 
138     QJsonDocument doc = QJsonDocument::fromVariant( _variant );
139     if ( ok )
140     {
141       *ok = !doc.isNull();
142     }
143     if ( errorString && !ok )
144     {
145       *errorString = QByteArray( "Failed to convert from variant" );
146     }
147     return doc.toJson( indented ? QJsonDocument::Indented : QJsonDocument::Compact );
148 #else
149     QJson::Serializer serializer;
150     serializer.setIndentMode( indented ? QJson::IndentFull : QJson::IndentCompact );
151     QByteArray jsondata = serializer.serialize( variant, ok );
152     if ( errorString && !ok )
153     {
154       *errorString = serializer.errorMessage().toUtf8();
155     }
156     return jsondata;
157 #endif
158   }
159 
160 }
161