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

Commit 356c0ae

Browse files
committed
Add fallback support for IDictionary types like OrderedDictionary
1 parent 8f3f4b4 commit 356c0ae

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

src/ServiceStack.Text/Common/DeserializeDictionary.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public static ParseStringDelegate GetParseMethod(Type type)
4242
{
4343
return GetParseMethod(typeof(Dictionary<object, object>));
4444
}
45+
if (typeof(IDictionary).IsAssignableFromType(type))
46+
{
47+
return s => ParseIDictionary(s, type);
48+
}
49+
4550
throw new ArgumentException(string.Format("Type {0} is not of type IDictionary<,>", type.FullName));
4651
}
4752

@@ -122,6 +127,46 @@ public static Dictionary<string, string> ParseStringDictionary(string value)
122127
return result;
123128
}
124129

130+
public static IDictionary ParseIDictionary(string value, Type dictType)
131+
{
132+
if (value == null) return null;
133+
134+
var index = VerifyAndGetStartIndex(value, dictType);
135+
136+
var valueParseMethod = Serializer.GetParseFn(typeof(object));
137+
if (valueParseMethod == null) return null;
138+
139+
var to = (IDictionary)dictType.CreateInstance();
140+
141+
if (JsonTypeSerializer.IsEmptyMap(value, index)) return to;
142+
143+
var valueLength = value.Length;
144+
while (index < valueLength)
145+
{
146+
var keyValue = Serializer.EatMapKey(value, ref index);
147+
Serializer.EatMapKeySeperator(value, ref index);
148+
var elementStartIndex = index;
149+
var elementValue = Serializer.EatTypeValue(value, ref index);
150+
if (keyValue == null) continue;
151+
152+
var mapKey = valueParseMethod(keyValue);
153+
154+
if (elementStartIndex < valueLength)
155+
{
156+
Serializer.EatWhitespace(value, ref elementStartIndex);
157+
to[mapKey] = DeserializeType<TSerializer>.ParsePrimitive(elementValue, value[elementStartIndex]);
158+
}
159+
else
160+
{
161+
to[mapKey] = valueParseMethod(elementValue);
162+
}
163+
164+
Serializer.EatItemSeperatorOrMapEndChar(value, ref index);
165+
}
166+
167+
return to;
168+
}
169+
125170
public static IDictionary<TKey, TValue> ParseDictionary<TKey, TValue>(
126171
string value, Type createMapType,
127172
ParseStringDelegate parseKeyFn, ParseStringDelegate parseValueFn)

tests/ServiceStack.Text.Tests/DictionaryTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Specialized;
34
using System.Diagnostics;
45
using NUnit.Framework;
56
using ServiceStack.Text.Tests.DynamicModels.DataModel;
@@ -500,6 +501,60 @@ public void Nongeneric_implementors_of_IDictionary_K_V_Should_serialize_like_Dic
500501
IDictionary<string, object> dict = expando;
501502
Assert.AreEqual(dict.Dump(), new Dictionary<string, object>(dict).Dump());
502503
}
504+
505+
[Test]
506+
public void Can_serialize_OrderedDictionary()
507+
{
508+
var dto = new OrderedDictionary { { "A", 1 }, { "B", "2" }, { "C", true } };
509+
var to = Serialize(dto, includeXml: false);
510+
511+
Assert.That(to["A"], Is.EqualTo(1));
512+
Assert.That(to["B"], Is.EqualTo("2"));
513+
Assert.That(to["C"], Is.EqualTo(true));
514+
}
515+
516+
[Test]
517+
public void Can_deserialize_ordereddictionary()
518+
{
519+
var original = new OrderedDictionary {
520+
{"Key1", "Value1"},
521+
{"Key2", 2},
522+
{3, "Value3"},
523+
{"Key4", false}
524+
};
525+
var json = JsonSerializer.SerializeToString(original);
526+
var deserialized = JsonSerializer.DeserializeFromString<OrderedDictionary>(json);
527+
528+
json.Print();
529+
530+
Assert.That(deserialized, Is.Not.Null);
531+
Assert.That(deserialized["Key1"], Is.EqualTo("Value1"));
532+
Assert.That(deserialized["Key2"], Is.EqualTo(2));
533+
Assert.That(deserialized[2], Is.EqualTo("Value3"));
534+
Assert.That(deserialized["Key4"], Is.EqualTo(false));
535+
}
536+
537+
[Test]
538+
public void Can_deserialize_ordereddictionary_subclass()
539+
{
540+
var original = new OrderedDictionarySub {
541+
{"Key1", "Value1"},
542+
{"Key2", 2},
543+
{3, "Value3"},
544+
{"Key4", false}
545+
};
546+
var json = JsonSerializer.SerializeToString(original);
547+
var deserialized = JsonSerializer.DeserializeFromString<OrderedDictionarySub>(json);
548+
549+
json.Print();
550+
551+
Assert.That(deserialized, Is.Not.Null);
552+
Assert.That(deserialized["Key1"], Is.EqualTo("Value1"));
553+
Assert.That(deserialized["Key2"], Is.EqualTo(2));
554+
Assert.That(deserialized[2], Is.EqualTo("Value3"));
555+
Assert.That(deserialized["Key4"], Is.EqualTo(false));
556+
}
503557
}
504558

559+
public class OrderedDictionarySub : OrderedDictionary {}
505560
}

0 commit comments

Comments
 (0)