@@ -16,15 +16,18 @@ public class ButtplugJsonMessageParser
1616 {
1717 [ NotNull ]
1818 private readonly Dictionary < string , Type > _messageTypes ;
19- [ NotNull ]
2019 private readonly IButtplugLog _bpLogger ;
2120 [ NotNull ]
2221 private readonly JsonSchema4 _schema ;
2322
23+ [ NotNull ]
24+ private JsonSerializer _serializer ;
25+
2426 public ButtplugJsonMessageParser ( IButtplugLogManager aLogManager = null )
2527 {
2628 _bpLogger = aLogManager . GetLogger ( GetType ( ) ) ;
2729 _bpLogger ? . Info ( $ "Setting up { GetType ( ) . Name } ") ;
30+ _serializer = new JsonSerializer { MissingMemberHandling = MissingMemberHandling . Error } ;
2831 IEnumerable < Type > allTypes ;
2932
3033 // Some classes in the library may not load on certain platforms due to missing symbols.
@@ -131,56 +134,77 @@ public ButtplugMessage[] Deserialize(string aJsonMsg)
131134 continue ;
132135 }
133136
134- var s = new JsonSerializer { MissingMemberHandling = MissingMemberHandling . Error } ;
135-
136137 // This specifically could fail due to object conversion.
137- try
138- {
139- var r = o [ msgName ] . Value < JObject > ( ) ;
140- res . Add ( ( ButtplugMessage ) r . ToObject ( _messageTypes [ msgName ] , s ) ) ;
141- _bpLogger ? . Trace ( $ "Message successfully parsed as { msgName } type") ;
142- }
143- catch ( InvalidCastException e )
144- {
145- var err = new Error ( $ "Could not create message for JSON { aJsonMsg } : { e . Message } ", ErrorClass . ERROR_MSG , ButtplugConsts . SystemMsgId ) ;
146- _bpLogger ? . LogErrorMsg ( err ) ;
147- res . Add ( err ) ;
148- }
149- catch ( JsonSerializationException e )
150- {
151- var err = new Error ( $ "Could not create message for JSON { aJsonMsg } : { e . Message } ", ErrorClass . ERROR_MSG , ButtplugConsts . SystemMsgId ) ;
152- _bpLogger ? . LogErrorMsg ( err ) ;
153- res . Add ( err ) ;
154- }
138+ res . Add ( DeserializeAs ( o , _messageTypes [ msgName ] , msgName , aJsonMsg ) ) ;
155139 }
156140
157141 return res . ToArray ( ) ;
158142 }
159143
144+ private ButtplugMessage DeserializeAs ( JObject aObject , Type aMsgType , string aMsgName , string aJsonMsg )
145+ {
146+ try
147+ {
148+ var r = aObject [ aMsgName ] . Value < JObject > ( ) ;
149+ var msg = ( ButtplugMessage ) r . ToObject ( aMsgType , _serializer ) ;
150+ _bpLogger ? . Trace ( $ "Message successfully parsed as { aMsgName } type") ;
151+ return msg ;
152+ }
153+ catch ( InvalidCastException e )
154+ {
155+ var err = new Error ( $ "Could not create message for JSON { aJsonMsg } : { e . Message } ", ErrorClass . ERROR_MSG , ButtplugConsts . SystemMsgId ) ;
156+ _bpLogger ? . LogErrorMsg ( err ) ;
157+ return err ;
158+ }
159+ catch ( JsonSerializationException e )
160+ {
161+ // Object didn't fit. Downgrade?
162+ var tmp = ( ButtplugMessage ) aMsgType . GetConstructor (
163+ BindingFlags . NonPublic | BindingFlags . Instance ,
164+ null , Type . EmptyTypes , null ) ? . Invoke ( null ) ;
165+ if ( tmp ? . PreviousType != null )
166+ {
167+ var msg = DeserializeAs ( aObject , tmp . PreviousType , aMsgName , aJsonMsg ) ;
168+ if ( ! ( msg is Error ) )
169+ {
170+ return msg ;
171+ }
172+ }
173+
174+ var err = new Error ( $ "Could not create message for JSON { aJsonMsg } : { e . Message } ", ErrorClass . ERROR_MSG , ButtplugConsts . SystemMsgId ) ;
175+ _bpLogger ? . LogErrorMsg ( err ) ;
176+ return err ;
177+ }
178+ }
179+
160180 public string Serialize ( [ NotNull ] ButtplugMessage aMsg , uint clientSchemaVersion )
161181 {
162182 // Warning: Any log messages in this function must be localOnly. They will possibly recurse.
163183
164184 // Support downgrading messages
165185 var tmp = aMsg ;
166- while ( tmp . SchemaVersion > clientSchemaVersion )
186+ while ( tmp == null || tmp . SchemaVersion > clientSchemaVersion )
167187 {
168- if ( tmp . PreviousType == null )
188+ if ( tmp ? . PreviousType == null )
169189 {
170- if ( tmp . Id == ButtplugConsts . SystemMsgId )
190+ if ( aMsg . Id == ButtplugConsts . SystemMsgId )
171191 {
172192 // There's no previous version of this system message
173193 _bpLogger ? . Warn ( $ "No messages serialized!") ;
174194 return null ;
175195 }
176196
177- tmp = new Error ( $ "No backwards compatible version for message #{ tmp . GetType ( ) . Name } !",
178- ErrorClass . ERROR_MSG , tmp . Id ) ;
179- continue ;
197+ var err = new Error ( $ "No backwards compatible version for message #{ aMsg . GetType ( ) . Name } !",
198+ ErrorClass . ERROR_MSG , aMsg . Id ) ;
199+ var eo = new JObject ( new JProperty ( err . GetType ( ) . Name , JObject . FromObject ( err ) ) ) ;
200+ var ea = new JArray ( eo ) ;
201+ _bpLogger ? . Error ( err . ErrorMessage , true ) ;
202+ _bpLogger ? . Trace ( $ "Message serialized to: { ea . ToString ( Formatting . None ) } ", true ) ;
203+ return ea . ToString ( Formatting . None ) ;
180204 }
181205
182206 tmp = ( ButtplugMessage ) aMsg . PreviousType . GetConstructor (
183- new Type [ ] { tmp . GetType ( ) } ) . Invoke ( new object [ ] { tmp } ) ;
207+ new Type [ ] { tmp . GetType ( ) } ) ? . Invoke ( new object [ ] { tmp } ) ;
184208 }
185209
186210 var o = new JObject ( new JProperty ( aMsg . GetType ( ) . Name , JObject . FromObject ( tmp ) ) ) ;
0 commit comments