Skip to content

Commit 4bb2a90

Browse files
committed
Add ToMessagePackObject FromMessagePackObject. #90
This commit add ToMessagePackObject and FromMessagePackObject extension methods to MessagePackSerializer and MessagePackSerializer<T>. These method enables packing/unpacking to/from MessagePackObject Instead of streams. For example, you can unpacking as MessagePackObject and then deserialize it to actual object. This commit also includes unit tests.
1 parent 7febd0d commit 4bb2a90

12 files changed

+799
-15
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,4 +609,5 @@ Release 0.9.0 (planned)
609609
* Runtime type polymorphism now supports name based type verification. This feature allows to prevent loading malicious or unknown types ibefore assembly loading.
610610
* Asymmetric serializers. You can generate "pack only" serializer when you set SerializationContext.CompabilityOptions.AllowAsymmetricSerializer to true. #68.
611611
* Built in serializer for System.Text.StringBuilder now supports UnpackTo.
612+
* Add serialization to/from MessagePackObject as extension methods of MessagePackSerializer and MessagePackSerializer<T>. Issue #90
612613

src/MsgPack/Serialization/MessagePackSerializerExtensions.cs

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2014 FUJIWARA, Yusuke
5+
// Copyright (C) 2014-2016 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -79,7 +79,7 @@ public static void Pack( this MessagePackSerializer source, Stream stream, objec
7979
}
8080

8181
/// <summary>
82-
/// Deserialize object from the <see cref="Stream"/>.
82+
/// Deserializes object from the <see cref="Stream"/>.
8383
/// </summary>
8484
/// <param name="source"><see cref="MessagePackSerializer"/> object.</param>
8585
/// <param name="stream">Source <see cref="Stream"/>.</param>
@@ -112,5 +112,128 @@ public static object Unpack( this MessagePackSerializer source, Stream stream )
112112

113113
return source.UnpackFrom( unpacker );
114114
}
115+
116+
/// <summary>
117+
/// Serializes object as a single <see cref="MessagePackObject"/>.
118+
/// </summary>
119+
/// <param name="source"><see cref="MessagePackSerializer"/> object.</param>
120+
/// <param name="obj">The object to be serialized.</param>
121+
/// <returns><see cref="MessagePackObject"/>.</returns>
122+
/// <exception cref="ArgumentNullException">
123+
/// <paramref name="source"/> is <c>null</c>.
124+
/// </exception>
125+
/// <exception cref="System.Runtime.Serialization.SerializationException">
126+
/// Failed to serialize.
127+
/// </exception>
128+
public static MessagePackObject ToMessagePackObject( this MessagePackSerializer source, object obj )
129+
{
130+
if ( source == null )
131+
{
132+
throw new ArgumentNullException( "source" );
133+
}
134+
135+
using ( var buffer = new MemoryStream() )
136+
{
137+
source.Pack( buffer, obj );
138+
buffer.Position = 0;
139+
return Unpacking.UnpackObject( buffer );
140+
}
141+
}
142+
143+
/// <summary>
144+
/// Serializes object as a single <see cref="MessagePackObject"/>.
145+
/// </summary>
146+
/// <typeparam name="T">The type of the object to be serialized.</typeparam>
147+
/// <param name="source"><see cref="MessagePackSerializer{T}"/> object.</param>
148+
/// <param name="obj">The object to be serialized.</param>
149+
/// <returns><see cref="MessagePackObject"/>.</returns>
150+
/// <exception cref="ArgumentNullException">
151+
/// <paramref name="source"/> is <c>null</c>.
152+
/// </exception>
153+
/// <exception cref="System.Runtime.Serialization.SerializationException">
154+
/// Failed to serialize.
155+
/// </exception>
156+
public static MessagePackObject ToMessagePackObject<T>( this MessagePackSerializer<T> source, T obj )
157+
{
158+
if ( source == null )
159+
{
160+
throw new ArgumentNullException( "source" );
161+
}
162+
163+
using ( var buffer = new MemoryStream() )
164+
{
165+
source.Pack( buffer, obj );
166+
buffer.Position = 0;
167+
return Unpacking.UnpackObject( buffer );
168+
}
169+
}
170+
171+
/// <summary>
172+
/// Deserializes object from a single <see cref="MessagePackObject"/>.
173+
/// </summary>
174+
/// <param name="source"><see cref="MessagePackSerializer"/> object.</param>
175+
/// <param name="mpo">The <see cref="MessagePackObject"/> which represents deserializing object structructure.</param>
176+
/// <returns>A deserialized object. This value can be <c>null</c>.</returns>
177+
/// <exception cref="ArgumentNullException">
178+
/// <paramref name="source"/> is <c>null</c>.
179+
/// </exception>
180+
/// <exception cref="System.Runtime.Serialization.SerializationException">
181+
/// Failed to deserialize.
182+
/// </exception>
183+
public static object FromMessagePackObject( this MessagePackSerializer source, MessagePackObject mpo )
184+
{
185+
if ( source == null )
186+
{
187+
throw new ArgumentNullException( "source" );
188+
}
189+
190+
// This idea is borrowed from @TSnake41
191+
using ( var buffer = new MemoryStream() )
192+
{
193+
using ( var packer = Packer.Create( buffer, PackerCompatibilityOptions.None, ownsStream: false ) )
194+
{
195+
mpo.PackToMessage( packer, null );
196+
}
197+
198+
buffer.Position = 0;
199+
200+
return source.Unpack( buffer );
201+
}
202+
}
203+
204+
/// <summary>
205+
/// Deserializes object from a single <see cref="MessagePackObject"/>.
206+
/// </summary>
207+
/// <typeparam name="T">The type of the object to be deserialized.</typeparam>
208+
/// <param name="source"><see cref="MessagePackSerializer{T}"/> object.</param>
209+
/// <param name="mpo">The <see cref="MessagePackObject"/> which represents deserializing object structructure.</param>
210+
/// <returns>A deserialized object. This value can be <c>null</c>.</returns>
211+
/// <exception cref="ArgumentNullException">
212+
/// <paramref name="source"/> is <c>null</c>.
213+
/// </exception>
214+
/// <exception cref="System.Runtime.Serialization.SerializationException">
215+
/// Failed to deserialize.
216+
/// </exception>
217+
public static T FromMessagePackObject<T>( this MessagePackSerializer<T> source, MessagePackObject mpo )
218+
{
219+
if ( source == null )
220+
{
221+
throw new ArgumentNullException( "source" );
222+
}
223+
224+
// This idea is borrowed from @TSnake41
225+
using ( var buffer = new MemoryStream() )
226+
{
227+
using ( var packer = Packer.Create( buffer, PackerCompatibilityOptions.None, ownsStream: false ) )
228+
{
229+
mpo.PackToMessage( packer, null );
230+
}
231+
232+
buffer.Position = 0;
233+
234+
return source.Unpack( buffer );
235+
}
236+
}
115237
}
116238
}
239+

test/MsgPack.UnitTest.CodeDom/Serialization/ArrayCodeDomBasedAutoMessagePackSerializerTest.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8806,6 +8806,84 @@ private void TestAsymmetricPackOnlyCore<T>( Func<T> factory, SerializerCapabilit
88068806

88078807
#endregion -- Asymmetric --
88088808

8809+
#region -- Object Packing/Unpacking --
8810+
8811+
[Test]
8812+
public void TestToFromMessagePackObject_Complex()
8813+
{
8814+
var target = new ComplexType() { Source = new Uri( "http://www.exambple.com" ), TimeStamp = DateTime.Now, Data = new byte[] { 0x1, 0x2, 0x3, 0x4 } };
8815+
target.History.Add( DateTime.Now.Subtract( TimeSpan.FromDays( 1 ) ), "Create New" );
8816+
target.Points.Add( 123 );
8817+
TestToFromMessagePackObjectCore(
8818+
target,
8819+
mpo =>
8820+
{
8821+
Assert.That( mpo.IsArray );
8822+
var asList = mpo.AsList();
8823+
Assert.That( asList.Count, Is.EqualTo( 5 ) );
8824+
8825+
Assert.That( asList[ 0 ].IsTypeOf<string>().Value );
8826+
Assert.That( asList[ 0 ].AsString(), Is.EqualTo( target.Source.ToString() ) );
8827+
8828+
Assert.That( asList[ 1 ].IsTypeOf<byte[]>().Value );
8829+
Assert.That( asList[ 1 ].AsBinary(), Is.EqualTo( target.Data ) );
8830+
8831+
Assert.That( asList[ 2 ].IsTypeOf<long>().Value );
8832+
Assert.That( asList[ 2 ].AsInt64(), Is.EqualTo( target.TimeStamp.ToBinary() ) );
8833+
8834+
Assert.That( asList[ 3 ].IsDictionary );
8835+
Assert.That( asList[ 3 ].AsDictionary().Single().Key.AsInt64(), Is.EqualTo( target.History.Single().Key.ToBinary() ) );
8836+
Assert.That( asList[ 3 ].AsDictionary().Single().Value.AsString(), Is.EqualTo( target.History.Single().Value ) );
8837+
8838+
Assert.That( asList[ 4 ].IsArray );
8839+
Assert.That( asList[ 4 ].AsList().Single().AsInt32(), Is.EqualTo( target.Points.Single() ) );
8840+
}
8841+
);
8842+
}
8843+
8844+
[Test]
8845+
public void TestToFromMessagePackObject_ComplexGenerated()
8846+
{
8847+
var target = new ComplexTypeGenerated();
8848+
target.Initialize();
8849+
// This test does not check packed result -- it is verfied with previous test and seems overkill.
8850+
this.TestToFromMessagePackObjectCore( target, _ => {} );
8851+
}
8852+
8853+
private void TestToFromMessagePackObjectCore<T>( T value, Action<MessagePackObject> mpoAssertion )
8854+
where T : IVerifiable<T>
8855+
{
8856+
this.TestToFromMessagePackObjectCore( value, mpoAssertion, true );
8857+
this.TestToFromMessagePackObjectCore( value, mpoAssertion, false );
8858+
}
8859+
8860+
private void TestToFromMessagePackObjectCore<T>( T value, Action<MessagePackObject> mpoAssertion, bool avoidsGenericSerializer )
8861+
where T : IVerifiable<T>
8862+
{
8863+
var previousAvoidsGenericSerializer = SerializerDebugging.AvoidsGenericSerializer;
8864+
SerializerDebugging.AvoidsGenericSerializer = avoidsGenericSerializer;
8865+
try
8866+
{
8867+
var context = GetSerializationContext();
8868+
var serializer = this.CreateTarget<T>( context );
8869+
var mpo = serializer.ToMessagePackObject( value );
8870+
mpoAssertion( mpo );
8871+
var result = serializer.FromMessagePackObject( mpo );
8872+
result.Verify( value );
8873+
8874+
var mpoLoose = ( ( MessagePackSerializer )serializer ).ToMessagePackObject( value );
8875+
mpoAssertion( mpoLoose );
8876+
var resultLoose = ( ( MessagePackSerializer )serializer ).FromMessagePackObject( mpoLoose );
8877+
Assert.That( resultLoose, Is.TypeOf<T>() );
8878+
( ( T )resultLoose ).Verify( value );
8879+
}
8880+
finally
8881+
{
8882+
SerializerDebugging.AvoidsGenericSerializer = previousAvoidsGenericSerializer;
8883+
}
8884+
}
8885+
8886+
#endregion -- Object Packing/Unpacking --
88098887
#region -- Polymorphism --
88108888
#region ---- KnownType ----
88118889

test/MsgPack.UnitTest.CodeDom/Serialization/MapCodeDomBasedAutoMessagePackSerializerTest.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9118,6 +9118,83 @@ private void TestAsymmetricPackOnlyCore<T>( Func<T> factory, SerializerCapabilit
91189118

91199119
#endregion -- Asymmetric --
91209120

9121+
#region -- Object Packing/Unpacking --
9122+
9123+
[Test]
9124+
public void TestToFromMessagePackObject_Complex()
9125+
{
9126+
var target = new ComplexType() { Source = new Uri( "http://www.exambple.com" ), TimeStamp = DateTime.Now, Data = new byte[] { 0x1, 0x2, 0x3, 0x4 } };
9127+
target.History.Add( DateTime.Now.Subtract( TimeSpan.FromDays( 1 ) ), "Create New" );
9128+
target.Points.Add( 123 );
9129+
TestToFromMessagePackObjectCore(
9130+
target,
9131+
mpo =>
9132+
{
9133+
Assert.That( mpo.IsDictionary );
9134+
var asDictionary = mpo.AsDictionary();
9135+
Assert.That( asDictionary.Count, Is.EqualTo( 5 ) );
9136+
9137+
Assert.That( asDictionary[ "Source" ].IsTypeOf<string>().Value );
9138+
Assert.That( asDictionary[ "Source" ].AsString(), Is.EqualTo( target.Source.ToString() ) );
9139+
9140+
Assert.That( asDictionary[ "Data" ].IsTypeOf<byte[]>().Value );
9141+
Assert.That( asDictionary[ "Data" ].AsBinary(), Is.EqualTo( target.Data ) );
9142+
9143+
Assert.That( asDictionary[ "TimeStamp" ].IsTypeOf<long>().Value );
9144+
Assert.That( asDictionary[ "TimeStamp" ].AsInt64(), Is.EqualTo( target.TimeStamp.ToBinary() ) );
9145+
9146+
Assert.That( asDictionary[ "History" ].AsDictionary().Single().Key.AsInt64(), Is.EqualTo( target.History.Single().Key.ToBinary() ) );
9147+
Assert.That( asDictionary[ "History" ].AsDictionary().Single().Value.AsString(), Is.EqualTo( target.History.Single().Value ) );
9148+
9149+
Assert.That( asDictionary[ "Points" ].IsArray );
9150+
Assert.That( asDictionary[ "Points" ].AsList().Single().AsInt32(), Is.EqualTo( target.Points.Single() ) );
9151+
}
9152+
);
9153+
}
9154+
9155+
[Test]
9156+
public void TestToFromMessagePackObject_ComplexGenerated()
9157+
{
9158+
var target = new ComplexTypeGenerated();
9159+
target.Initialize();
9160+
// This test does not check packed result -- it is verfied with previous test and seems overkill.
9161+
this.TestToFromMessagePackObjectCore( target, _ => {} );
9162+
}
9163+
9164+
private void TestToFromMessagePackObjectCore<T>( T value, Action<MessagePackObject> mpoAssertion )
9165+
where T : IVerifiable<T>
9166+
{
9167+
this.TestToFromMessagePackObjectCore( value, mpoAssertion, true );
9168+
this.TestToFromMessagePackObjectCore( value, mpoAssertion, false );
9169+
}
9170+
9171+
private void TestToFromMessagePackObjectCore<T>( T value, Action<MessagePackObject> mpoAssertion, bool avoidsGenericSerializer )
9172+
where T : IVerifiable<T>
9173+
{
9174+
var previousAvoidsGenericSerializer = SerializerDebugging.AvoidsGenericSerializer;
9175+
SerializerDebugging.AvoidsGenericSerializer = avoidsGenericSerializer;
9176+
try
9177+
{
9178+
var context = GetSerializationContext();
9179+
var serializer = this.CreateTarget<T>( context );
9180+
var mpo = serializer.ToMessagePackObject( value );
9181+
mpoAssertion( mpo );
9182+
var result = serializer.FromMessagePackObject( mpo );
9183+
result.Verify( value );
9184+
9185+
var mpoLoose = ( ( MessagePackSerializer )serializer ).ToMessagePackObject( value );
9186+
mpoAssertion( mpoLoose );
9187+
var resultLoose = ( ( MessagePackSerializer )serializer ).FromMessagePackObject( mpoLoose );
9188+
Assert.That( resultLoose, Is.TypeOf<T>() );
9189+
( ( T )resultLoose ).Verify( value );
9190+
}
9191+
finally
9192+
{
9193+
SerializerDebugging.AvoidsGenericSerializer = previousAvoidsGenericSerializer;
9194+
}
9195+
}
9196+
9197+
#endregion -- Object Packing/Unpacking --
91219198
#region -- Polymorphism --
91229199
#region ---- KnownType ----
91239200

0 commit comments

Comments
 (0)