2626import org .eclipse .emf .ecore .resource .ResourceSet ;
2727import org .eclipse .emf .ecore .util .EcoreUtil ;
2828import org .emfjson .EMFJs ;
29- import org .emfjson .jackson .common .Cache ;
3029import org .emfjson .common .EObjects ;
3130import org .emfjson .common .ReferenceEntries ;
3231import org .emfjson .jackson .JacksonOptions ;
32+ import org .emfjson .jackson .common .Cache ;
3333import org .emfjson .jackson .errors .JSONException ;
3434import org .emfjson .jackson .resource .JsonResource ;
3535
3636import java .io .IOException ;
37+ import java .util .Collection ;
3738import java .util .Map ;
3839
3940public class EObjectDeserializer extends JsonDeserializer <EObject > implements ContextualDeserializer {
@@ -134,7 +135,11 @@ protected EObject doDeserialize(JsonParser jp, EClass defaultType, Deserializati
134135 return postDeserialize (buffer , current , defaultType , ctxt );
135136 }
136137
137- protected EObject postDeserialize (TokenBuffer buffer , EObject object , EClass defaultType , DeserializationContext ctxt ) throws IOException {
138+ protected EObject postDeserialize (TokenBuffer buffer ,
139+ EObject object ,
140+ EClass defaultType ,
141+ DeserializationContext ctxt ) throws IOException {
142+
138143 if (object == null && defaultType == null ) {
139144 return null ;
140145 }
@@ -172,9 +177,12 @@ private EClass findRoot(DeserializationContext ctxt) {
172177 return options .rootElement ;
173178 }
174179
175- private void readFeature (JsonParser jp , EObject current ,
176- String fieldName , DeserializationContext ctxt ,
177- Resource resource , ReferenceEntries entries ) throws IOException {
180+ private void readFeature (JsonParser jp ,
181+ EObject current ,
182+ String fieldName ,
183+ DeserializationContext ctxt ,
184+ Resource resource ,
185+ ReferenceEntries entries ) throws IOException {
178186
179187 final EClass eClass = current .eClass ();
180188 final EStructuralFeature feature = cache .getEStructuralFeature (eClass , fieldName );
@@ -211,71 +219,50 @@ private void readFeature(JsonParser jp, EObject current,
211219 }
212220
213221 @ SuppressWarnings ("unchecked" )
214- private void readContainment (JsonParser jp , EObject owner ,
215- DeserializationContext ctxt , EReference reference ,
216- Resource resource , ReferenceEntries entries ) throws IOException {
222+ private void readContainment (JsonParser jp ,
223+ EObject owner ,
224+ DeserializationContext ctxt ,
225+ EReference reference ,
226+ Resource resource ,
227+ ReferenceEntries entries ) throws IOException {
217228
218- final Class <?> type = reference .getEReferenceType ().getInstanceClass ();
229+ final EClass eType = (EClass ) owner .eClass ().getFeatureType (reference ).getEClassifier ();
230+ final Class <?> type = eType .getInstanceClass ();
219231
220- if (type != null && Map .Entry .class .isAssignableFrom (type )) {
221- EMap map = (EMap ) owner .eGet (reference );
222-
223- if (jp .getCurrentToken () == JsonToken .START_OBJECT ) {
232+ if (jp .getCurrentToken () == JsonToken .START_ARRAY ) {
224233
225- while (jp .nextToken () != JsonToken .END_OBJECT ) {
226- EObject entry = EObjects .createEntry (jp .getCurrentName (), jp .nextTextValue ());
227- map .add (entry );
228- }
234+ while (jp .nextToken () != JsonToken .END_ARRAY ) {
229235
230- } else if (jp .getCurrentToken () == JsonToken .START_ARRAY ) {
231-
232- while (jp .nextToken () != JsonToken .END_ARRAY ) {
233- EObject key = null ;
234- EObject value = null ;
235-
236- if (jp .getCurrentToken () == JsonToken .START_OBJECT ) {
237- while (jp .nextToken () != JsonToken .END_OBJECT ) {
238- if ("key" .equals ( jp .getCurrentName () )) {
239- jp .nextToken ();
240- key = deserialize (jp , ctxt , reference );
241- } else if ("value" .equals ( jp .getCurrentName () )) {
242- jp .nextToken ();
243- value = deserialize (jp , ctxt , reference );
244- }
245- }
236+ try {
237+ EObject value = deserialize (jp , ctxt , reference );
238+ if (value != null ) {
239+ EObjects .setOrAdd (owner , reference , value );
240+ entries .store (resource , value );
246241 }
247-
248- if (key != null && value != null ) {
249- map . put ( key , value );
242+ } catch ( Exception e ) {
243+ if (resource != null ) {
244+ resource . getErrors (). add ( new JSONException ( e , jp . getCurrentLocation ()) );
250245 }
251246 }
252247 }
253248
254249 } else {
255250
256- if (jp .getCurrentToken () == JsonToken .START_ARRAY ) {
257- while (jp .nextToken () != JsonToken .END_ARRAY ) {
258-
259- try {
260- EObject value = deserialize (jp , ctxt , reference );
261- if (value != null ) {
262- EObjects .setOrAdd (owner , reference , value );
263- entries .store (resource , value );
264- }
265- } catch (Exception e ) {
266- if (resource != null ) {
267- resource .getErrors ().add (new JSONException (e , jp .getCurrentLocation ()));
268- }
269- }
270- }
271- } else {
251+ // if the type is a Map.Entry but the current values are not serialized
252+ // in an array, then it must be a map with string keys that was serialized
253+ // as a JSON object.
254+ if ((type != null && Map .Entry .class .isAssignableFrom (type )) || "java.util.Map.Entry" .equals (eType .getInstanceClassName ())) {
272255
256+ readMap (jp , owner , ctxt , reference );
257+
258+ } else {
259+ // otherwise it's a normal object.
273260 try {
274261 EObject value = deserialize (jp , ctxt , reference );
275262 if (value != null ) {
276263 entries .store (resource , value );
264+ EObjects .setOrAdd (owner , reference , value );
277265 }
278- EObjects .setOrAdd (owner , reference , value );
279266 } catch (Exception e ) {
280267 if (resource != null ) {
281268 resource .getErrors ().add (new JSONException (e , jp .getCurrentLocation ()));
@@ -285,8 +272,45 @@ private void readContainment(JsonParser jp, EObject owner,
285272 }
286273 }
287274
288- private void readReference (JsonParser jp , EObject owner ,
289- EReference reference , ReferenceEntries entries ,
275+ /*
276+ Read the key-values pair of a JSON object and put it in a Map.
277+ */
278+ @ SuppressWarnings ("unchecked" )
279+ private void readMap (JsonParser jp ,
280+ EObject owner ,
281+ DeserializationContext ctxt ,
282+ EReference reference ) throws IOException {
283+
284+ final Collection map = (Collection ) owner .eGet (reference );
285+
286+ if (jp .getCurrentToken () == JsonToken .START_OBJECT ) {
287+
288+ while (jp .nextToken () != JsonToken .END_OBJECT ) {
289+ final String key = jp .getCurrentName ();
290+ jp .nextToken ();
291+
292+ final Object value ;
293+ if (jp .getCurrentToken () == JsonToken .START_OBJECT ) {
294+ value = deserialize (jp , ctxt , reference );
295+ } else {
296+ value = ctxt .readValue (jp , Object .class );
297+ }
298+
299+ // Dynamic objects do not use the EMap interface
300+ // but store entries in a DynamicEList instead.
301+ if (map instanceof EMap ) {
302+ ((EMap ) map ).put (key , value );
303+ } else {
304+ map .add (EObjects .createEntry (key , value , reference .getEReferenceType ()));
305+ }
306+ }
307+ }
308+ }
309+
310+ private void readReference (JsonParser jp ,
311+ EObject owner ,
312+ EReference reference ,
313+ ReferenceEntries entries ,
290314 DeserializationContext context ) throws IOException {
291315
292316 if (jp .getCurrentToken () == JsonToken .START_ARRAY ) {
@@ -298,9 +322,12 @@ private void readReference(JsonParser jp, EObject owner,
298322 }
299323 }
300324
301- private void readAttribute (JsonParser jp , EObject owner ,
302- EAttribute attribute , Resource resource ,
325+ private void readAttribute (JsonParser jp ,
326+ EObject owner ,
327+ EAttribute attribute ,
328+ Resource resource ,
303329 DeserializationContext ctxt ) throws IOException {
330+
304331 final EDataType dataType = (EDataType ) owner .eClass ().getFeatureType (attribute ).getEClassifier ();
305332 if (dataType == null ) {
306333 resource .getErrors ().add (new JSONException ("Missing feature type" , jp .getCurrentLocation ()));
@@ -317,8 +344,10 @@ private void readAttribute(JsonParser jp, EObject owner,
317344 }
318345 }
319346
320- private void readSingleAttribute (JsonParser jp , EObject owner ,
321- EAttribute attribute , Resource resource ,
347+ private void readSingleAttribute (JsonParser jp ,
348+ EObject owner ,
349+ EAttribute attribute ,
350+ Resource resource ,
322351 EDataType dataType ,
323352 DeserializationContext ctxt ) throws IOException {
324353
0 commit comments