@@ -198,91 +198,32 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
198198 writer . WriteStartObject ( ) ;
199199
200200 var resourceType = value . GetType ( ) ;
201-
202- // Write the type
203- writer . WritePropertyName ( "type" ) ;
204201 var jsonTypeKey = _modelManager . GetResourceTypeNameForType ( resourceType ) ;
205- writer . WriteValue ( jsonTypeKey ) ;
206-
207- // Do the Id now...
208- writer . WritePropertyName ( "id" ) ;
209202 var idProp = _modelManager . GetIdProperty ( resourceType ) ;
210- writer . WriteValue ( GetValueForIdProperty ( idProp , value ) ) ;
203+
204+ // Write the type and id
205+ WriteTypeAndId ( writer , resourceType , value ) ;
211206
212207 // Leverage the cached map to avoid another costly call to System.Type.GetProperties()
213208 var props = _modelManager . GetProperties ( value . GetType ( ) ) ;
214209
215- // Do non-model properties first, everything else goes in "links "
210+ // Do non-model properties first, everything else goes in "related "
216211 //TODO: Unless embedded???
217212 var relationshipModelProperties = new List < RelationshipModelProperty > ( ) ;
218213
219- foreach ( var modelProperty in props )
220- {
221- var prop = modelProperty . Property ;
222- if ( prop == idProp ) continue ; // Don't write the "id" property twice, see above!
223-
224- if ( modelProperty is FieldModelProperty )
225- {
226- if ( modelProperty . IgnoreByDefault ) continue ; // TODO: allow overriding this
227-
228- // numbers, strings, dates...
229- writer . WritePropertyName ( modelProperty . JsonKey ) ;
230-
231- var propertyValue = prop . GetValue ( value , null ) ;
232-
233- if ( prop . PropertyType == typeof ( Decimal ) || prop . PropertyType == typeof ( Decimal ? ) )
234- {
235- if ( propertyValue == null )
236- writer . WriteNull ( ) ;
237- else
238- writer . WriteValue ( propertyValue . ToString ( ) ) ;
239- }
240- else if ( prop . PropertyType == typeof ( string ) &&
241- prop . GetCustomAttributes ( ) . Any ( attr => attr is SerializeStringAsRawJsonAttribute ) )
242- {
243- if ( propertyValue == null )
244- {
245- writer . WriteNull ( ) ;
246- }
247- else
248- {
249- var json = ( string ) propertyValue ;
250- if ( ValidateRawJsonStrings )
251- {
252- try
253- {
254- var token = JToken . Parse ( json ) ;
255- json = token . ToString ( ) ;
256- }
257- catch ( Exception )
258- {
259- json = "{}" ;
260- }
261- }
262- var valueToSerialize = JsonHelpers . MinifyJson ( json ) ;
263- writer . WriteRawValue ( valueToSerialize ) ;
264- }
265- }
266- else
267- {
268- serializer . Serialize ( writer , propertyValue ) ;
269- }
270- }
271- else if ( modelProperty is RelationshipModelProperty )
272- {
273- relationshipModelProperties . Add ( ( RelationshipModelProperty ) modelProperty ) ;
274- }
275- }
214+ // Write attributes
215+ WriteAttributes ( props , writer , idProp , value , serializer , relationshipModelProperties ) ;
276216
277217 // Now do other stuff
278218 if ( relationshipModelProperties . Count ( ) > 0 )
279219 {
280- writer . WritePropertyName ( "links " ) ;
220+ writer . WritePropertyName ( "relastionships " ) ;
281221 writer . WriteStartObject ( ) ;
282222 }
283223 foreach ( var relationshipModelProperty in relationshipModelProperties )
284224 {
285- bool skip = false , iip = false ;
225+ bool skip = false ,
226+ iip = false ;
286227 string lt = null ;
287228 SerializeAsOptions sa = SerializeAsOptions . Ids ;
288229
@@ -324,11 +265,12 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
324265 switch ( sa )
325266 {
326267 case SerializeAsOptions . Ids :
327- //writer.WritePropertyName(ContractResolver._modelManager.GetJsonKeyForProperty(prop));
328268 IEnumerable < object > items = ( IEnumerable < object > ) prop . GetValue ( value , null ) ;
329269 if ( items == null )
330270 {
331- writer . WriteValue ( ( IEnumerable < object > ) null ) ; //TODO: Is it okay with the spec and Ember Data to return null for an empty array?
271+ // Return an empty array when there are no items
272+ writer . WriteStartArray ( ) ;
273+ writer . WriteEndArray ( ) ;
332274 break ; // LOOK OUT! Ending this case block early here!!!
333275 }
334276 this . WriteIdsArrayJson ( writer , items , serializer ) ;
@@ -354,7 +296,7 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
354296 //writer.WritePropertyName(ContractResolver._modelManager.GetJsonKeyForProperty(prop));
355297 //TODO: Support ids and type properties in "link" object
356298 writer . WriteStartObject ( ) ;
357- writer . WritePropertyName ( "related " ) ;
299+ writer . WritePropertyName ( "links " ) ;
358300 writer . WriteValue ( href ) ;
359301 writer . WriteEndObject ( ) ;
360302 break ;
@@ -383,8 +325,15 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
383325 switch ( sa )
384326 {
385327 case SerializeAsOptions . Ids :
386- //writer.WritePropertyName(ContractResolver._modelManager.GetJsonKeyForProperty(prop));
387- serializer . Serialize ( writer , objId . Value ) ;
328+ // Write the data element
329+ writer . WriteStartObject ( ) ;
330+ writer . WritePropertyName ( PrimaryDataKeyName ) ;
331+ writer . WriteStartObject ( ) ;
332+ // Write the type and id
333+ WriteTypeAndId ( writer , prop . PropertyType , propertyValue ) ;
334+
335+ writer . WriteEndObject ( ) ;
336+ writer . WriteEndObject ( ) ;
388337 if ( iip )
389338 if ( aggregator != null )
390339 aggregator . Add ( prop . PropertyType , propertyValue ) ;
@@ -398,7 +347,7 @@ protected void Serialize(object value, Stream writeStream, JsonWriter writer, Js
398347
399348 //writer.WritePropertyName(ContractResolver._modelManager.GetJsonKeyForProperty(prop));
400349 writer . WriteStartObject ( ) ;
401- writer . WritePropertyName ( "related " ) ;
350+ writer . WritePropertyName ( "links " ) ;
402351 writer . WriteValue ( link ) ;
403352 writer . WriteEndObject ( ) ;
404353 break ;
@@ -492,7 +441,7 @@ protected void SerializeLinkedResources(Stream writeStream, JsonWriter writer, J
492441
493442 if ( aggregator . Appendices . Count > 0 )
494443 {
495- writer . WritePropertyName ( "linked " ) ;
444+ writer . WritePropertyName ( "included " ) ;
496445 writer . WriteStartObject ( ) ;
497446
498447 // Okay, we should have captured everything now. Now combine the type writers into the main writer...
@@ -509,6 +458,76 @@ protected void SerializeLinkedResources(Stream writeStream, JsonWriter writer, J
509458
510459 }
511460
461+ private void WriteAttributes ( ModelProperty [ ] props , JsonWriter writer , PropertyInfo idProp , object value , JsonSerializer serializer , List < RelationshipModelProperty > relationshipModelProperties )
462+ {
463+ //if (props.Count() > 0)
464+ //{
465+ // writer.WritePropertyName("attributes");
466+ // writer.WriteStartObject();
467+ //}
468+
469+ foreach ( var modelProperty in props )
470+ {
471+ var prop = modelProperty . Property ;
472+ if ( prop == idProp ) continue ; // Don't write the "id" property twice, see above!
473+
474+ if ( modelProperty is FieldModelProperty )
475+ {
476+ if ( modelProperty . IgnoreByDefault ) continue ; // TODO: allow overriding this
477+
478+ // numbers, strings, dates...
479+ writer . WritePropertyName ( modelProperty . JsonKey ) ;
480+
481+ var propertyValue = prop . GetValue ( value , null ) ;
482+
483+ if ( prop . PropertyType == typeof ( Decimal ) || prop . PropertyType == typeof ( Decimal ? ) )
484+ {
485+ if ( propertyValue == null )
486+ writer . WriteNull ( ) ;
487+ else
488+ writer . WriteValue ( propertyValue ) ;
489+ }
490+ else if ( prop . PropertyType == typeof ( string ) &&
491+ prop . GetCustomAttributes ( ) . Any ( attr => attr is SerializeStringAsRawJsonAttribute ) )
492+ {
493+ if ( propertyValue == null )
494+ {
495+ writer . WriteNull ( ) ;
496+ }
497+ else
498+ {
499+ var json = ( string ) propertyValue ;
500+ if ( ValidateRawJsonStrings )
501+ {
502+ try
503+ {
504+ var token = JToken . Parse ( json ) ;
505+ json = token . ToString ( ) ;
506+ }
507+ catch ( Exception )
508+ {
509+ json = "{}" ;
510+ }
511+ }
512+ var valueToSerialize = JsonHelpers . MinifyJson ( json ) ;
513+ writer . WriteRawValue ( valueToSerialize ) ;
514+ }
515+ }
516+ else
517+ {
518+ serializer . Serialize ( writer , propertyValue ) ;
519+ }
520+ }
521+ else if ( modelProperty is RelationshipModelProperty )
522+ {
523+ relationshipModelProperties . Add ( ( RelationshipModelProperty ) modelProperty ) ;
524+ }
525+ }
526+
527+ //if (props.Count() > 0)
528+ // writer.WriteEndObject();
529+ }
530+
512531 #endregion Serialization
513532
514533 #region Deserialization
@@ -558,11 +577,11 @@ private object ReadFromStream(Type type, Stream readStream, HttpContent content,
558577 reader . Read ( ) ; // burn the PropertyName token
559578 switch ( value )
560579 {
561- case "linked " :
580+ case "included " :
562581 //TODO: If we want to capture linked/related objects in a compound document when deserializing, do it here...do we?
563582 reader . Skip ( ) ;
564583 break ;
565- case "links " :
584+ case "relationships " :
566585 // ignore this, is it even meaningful in a PUT/POST body?
567586 reader . Skip ( ) ;
568587 break ;
@@ -712,7 +731,7 @@ private object Deserialize(Type objectType, JsonReader reader)
712731 string value = ( string ) reader . Value ;
713732 var modelProperty = _modelManager . GetPropertyForJsonKey ( objectType , value ) ;
714733
715- if ( value == "links " )
734+ if ( value == "related " )
716735 {
717736 reader . Read ( ) ; // burn the PropertyName token
718737 //TODO: linked resources (Done??)
@@ -724,7 +743,7 @@ private object Deserialize(Type objectType, JsonReader reader)
724743 {
725744 reader . Read ( ) ; // burn the PropertyName token
726745 //TODO: Embedded would be dropped here!
727- continue ; // These aren't supposed to be here, they're supposed to be in "links "!
746+ continue ; // These aren't supposed to be here, they're supposed to be in "related "!
728747 }
729748
730749 var prop = modelProperty . Property ;
@@ -1008,16 +1027,31 @@ protected string GetIdFor(object obj)
10081027 return GetValueForIdProperty ( idprop , obj ) ;
10091028 }
10101029
1030+ private void WriteTypeAndId ( JsonWriter writer , Type propertyType , object propertyValue )
1031+ {
1032+ writer . WritePropertyName ( "type" ) ;
1033+ writer . WriteValue ( _modelManager . GetResourceTypeNameForType ( propertyType ) ) ;
1034+
1035+ writer . WritePropertyName ( "id" ) ;
1036+ writer . WriteValue ( GetValueForIdProperty ( _modelManager . GetIdProperty ( propertyType ) , propertyValue ) ) ;
1037+ }
1038+
10111039 private void WriteIdsArrayJson ( Newtonsoft . Json . JsonWriter writer , IEnumerable < object > value , Newtonsoft . Json . JsonSerializer serializer )
10121040 {
1041+ // Write the data element
1042+ writer . WriteStartObject ( ) ;
1043+ writer . WritePropertyName ( PrimaryDataKeyName ) ;
1044+
10131045 IEnumerator < Object > collectionEnumerator = ( value as IEnumerable < object > ) . GetEnumerator ( ) ;
10141046 writer . WriteStartArray ( ) ;
10151047 while ( collectionEnumerator . MoveNext ( ) )
10161048 {
1017- var serializable = collectionEnumerator . Current ;
1018- writer . WriteValue ( this . GetIdFor ( serializable ) ) ;
1049+ writer . WriteStartObject ( ) ;
1050+ WriteTypeAndId ( writer , collectionEnumerator . Current . GetType ( ) , collectionEnumerator . Current ) ;
1051+ writer . WriteEndObject ( ) ;
10191052 }
10201053 writer . WriteEndArray ( ) ;
1054+ writer . WriteEndObject ( ) ;
10211055 }
10221056
10231057 }
0 commit comments