Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 6322891

Browse files
committed
Add support of base collection with inherited types
1 parent 6321e25 commit 6322891

File tree

3 files changed

+81
-8
lines changed

3 files changed

+81
-8
lines changed

src/ServiceStack.Text/Common/WriteType.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,24 @@ public static void WriteAbstractProperties(TextWriter writer, object value)
356356
return;
357357
}
358358

359-
var writeFn = Serializer.GetWriteFn(valueType);
360-
if (!JsConfig<T>.ExcludeTypeInfo.GetValueOrDefault()) JsState.IsWritingDynamic = true;
361-
writeFn(writer, value);
362-
if (!JsConfig<T>.ExcludeTypeInfo.GetValueOrDefault()) JsState.IsWritingDynamic = false;
359+
WriteLateboundProperties(writer, value, valueType);
363360
}
364361

365362
public static void WriteProperties(TextWriter writer, object value)
366363
{
364+
if (value == null)
365+
{
366+
writer.Write(JsWriter.EmptyMap);
367+
return;
368+
}
369+
370+
var valueType = value.GetType();
371+
if (PropertyWriters != null && valueType != typeof(T) && !typeof(T).IsAbstract())
372+
{
373+
WriteLateboundProperties(writer, value, valueType);
374+
return;
375+
}
376+
367377
if (typeof(TSerializer) == typeof(JsonTypeSerializer) && JsState.WritingKeyCount > 0)
368378
writer.Write(JsWriter.QuoteChar);
369379

@@ -384,7 +394,7 @@ public static void WriteProperties(TextWriter writer, object value)
384394
{
385395
var propertyWriter = PropertyWriters[index];
386396

387-
if (value != null && propertyWriter.shouldSerialize != null && !propertyWriter.shouldSerialize((T)value))
397+
if (propertyWriter.shouldSerialize != null && !propertyWriter.shouldSerialize((T)value))
388398
continue;
389399

390400
var dontSkipDefault = false;
@@ -400,9 +410,7 @@ public static void WriteProperties(TextWriter writer, object value)
400410
}
401411
}
402412

403-
var propertyValue = value != null
404-
? propertyWriter.GetterFn((T)value)
405-
: null;
413+
var propertyValue = propertyWriter.GetterFn((T)value);
406414

407415
if (!dontSkipDefault)
408416
{
@@ -444,6 +452,14 @@ public static void WriteProperties(TextWriter writer, object value)
444452
writer.Write(JsWriter.QuoteChar);
445453
}
446454

455+
private static void WriteLateboundProperties(TextWriter writer, object value, Type valueType)
456+
{
457+
var writeFn = Serializer.GetWriteFn(valueType);
458+
if (!JsConfig<T>.ExcludeTypeInfo.GetValueOrDefault()) JsState.IsWritingDynamic = true;
459+
writeFn(writer, value);
460+
if (!JsConfig<T>.ExcludeTypeInfo.GetValueOrDefault()) JsState.IsWritingDynamic = false;
461+
}
462+
447463
private static readonly char[] ArrayBrackets = new[] { '[', ']' };
448464

449465
public static void WriteComplexQueryStringProperties(string typeName, TextWriter writer, object value)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using NUnit.Framework;
5+
using ServiceStack.Text.Tests.Support;
6+
7+
namespace ServiceStack.Text.Tests.JsonTests
8+
{
9+
[DataContract]
10+
public class MovieChild : Movie
11+
{
12+
public MovieChild()
13+
{
14+
this.Oscar = new List<string>();
15+
}
16+
17+
[DataMember]
18+
public List<string> Oscar { get; set; }
19+
}
20+
21+
class BlockBuster
22+
{
23+
public BlockBuster(string address)
24+
{
25+
this.Address = address;
26+
this.Movies = new List<Movie>();
27+
}
28+
29+
public string Address { get; set; }
30+
public List<Movie> Movies { get; set; }
31+
}
32+
33+
[TestFixture]
34+
public class InheritAbstractTests
35+
{
36+
[Test]
37+
public void Can_serialize_class_with_list_that_classes_inherited_from_non_abstract_class()
38+
{
39+
var child = new MovieChild { ImdbId = "tt0068646", Title = "The Godfather", Rating = 9.2m, Director = "Francis Ford Coppola", ReleaseDate = new DateTime(1972, 3, 24), TagLine = "An offer you can't refuse.", Genres = new List<string> { "Crime", "Drama", "Thriller" }, };
40+
child.Oscar.Add("Best Picture - 1972");
41+
child.Oscar.Add("Best Actor - 1972");
42+
child.Oscar.Add("Best Adapted Screenplay - 1972");
43+
44+
var blockBuster = new BlockBuster("Av. República do Líbano, 2175 - Indinópolis, São Paulo - SP, 04502-300");
45+
blockBuster.Movies.Add(MoviesData.Movies[0]);
46+
blockBuster.Movies.Add(child);
47+
48+
// serialize to JSON using ServiceStack
49+
string jsonString = JsonSerializer.SerializeToString(blockBuster);
50+
51+
const string expected = "{\"Address\":\"Av. República do Líbano, 2175 - Indinópolis, São Paulo - SP, 04502-300\",\"Movies\":[{\"Title\":\"The Shawshank Redemption\",\"ImdbId\":\"tt0111161\",\"Rating\":9.2,\"Director\":\"Frank Darabont\",\"ReleaseDate\":\"\\/Date(792950400000-0000)\\/\",\"TagLine\":\"Fear can hold you prisoner. Hope can set you free.\",\"Genres\":[\"Crime\",\"Drama\"]},{\"__type\":\"ServiceStack.Text.Tests.JsonTests.MovieChild, ServiceStack.Text.Tests\",\"Oscar\":[\"Best Picture - 1972\",\"Best Actor - 1972\",\"Best Adapted Screenplay - 1972\"],\"Title\":\"The Godfather\",\"ImdbId\":\"tt0068646\",\"Rating\":9.2,\"Director\":\"Francis Ford Coppola\",\"ReleaseDate\":\"\\/Date(70214400000-0000)\\/\",\"TagLine\":\"An offer you can't refuse.\",\"Genres\":[\"Crime\",\"Drama\",\"Thriller\"]}]}";
52+
53+
Assert.That(jsonString, Is.EqualTo(expected));
54+
}
55+
}
56+
}

tests/ServiceStack.Text.Tests/ServiceStack.Text.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@
180180
<Compile Include="AttributeTests.cs" />
181181
<Compile Include="CsvTypeTests.cs" />
182182
<Compile Include="HttpUtilsTests.cs" />
183+
<Compile Include="JsonTests\InheritAbstractTests.cs" />
183184
<Compile Include="JsonTests\JsonEnumTests.cs" />
184185
<Compile Include="JsonTests\InvalidJsonTests.cs" />
185186
<Compile Include="JsonTests\OnDeserializationErrorTests.cs" />

0 commit comments

Comments
 (0)