Deserializing an Array of Complex Types

Hey Jeff,

Thanks for all the help but I have another question for you. I have two .net classes:

public class User
     {
        [JsonProperty("id")]
        public string id { get; set; }
 
        [JsonProperty("complexType")]
        public List<ComplexType> complexType { get; set; }
 
        [JsonProperty("type")]
        public string Type
        {
            get { return "user"; }
        }
    }
 
    [DataContract]
    public class ComplexType
    {
 
        [JsonProperty("name")]
        public string name { get; set; }
 
        [JsonProperty("basicType ")]
        public List<string> basicType { get; set; }
    }

I need a union of all of the basicTypes data across all users. I wrote a view that emits all of the complex types across all the users and I get back any array of objects. What is the quickest and easiest way to cast them back to the original complexType variable they were store as? I tried the

client.GetView<ComplexType[]>... and  client.GetView<ComplexType>... and client.GetView<List<ComplexType>>  …  

But couchbase threw a casting error each time. Any help or directions would be much appreciated. I can send more details if you need them.

Thanks,
Stephen

Continued...

But it threw a casting error. Any help or directions would be much appreciated. I can send more details if you need them.

Thanks,
Stephen

This seems like a good approach. I'll let you know how it works out:

A more interesting approach would be to take advantage of C#'s new dynamic typing and the ExpandoObject class. These features allow developers to instruct the compiler to perform type checking at runtime, not at compile time. Working with JSON documents is a great use case for dynamics.

The dynamic extension methods are almost identical, except where before there were dictionaries, now there are dynamic types.
public static Tuple StoreDynamic(this ICouchbaseClient client, StoreMode storeMode,
string key, ExpandoObject obj)
{
var json = JsonConvert.SerializeObject(obj);
var result = client.ExecuteStore(storeMode, key, json);

if (!result.Success)
{
if (result.Exception != null) throw result.Exception as Exception;

return Tuple.Create(false, result.StatusCode.HasValue ? result.StatusCode.Value : -1, result.Message);
}

return Tuple.Create(true, 0, string.Empty);
}

public static Tuple GetDynamic(this ICouchbaseClient client, string key)
{
var result = client.ExecuteGet(key);

if (!result.Success)
{
if (result.Exception != null) throw result.Exception;

return Tuple.Create
(false, result.StatusCode.HasValue ? result.StatusCode.Value : -1, result.Message, null);
}

var obj = JsonConvert.DeserializeObject(result.Value);
return Tuple.Create(true, 0, string.Empty, obj);
}

Using dynamic instances in your code, you can then save and retrieve data to and from Couchbase Server. Note that you could also read any JSON document into an ExpandoObject using the code approach below. To test that, you can call GetDynamic with a key of "user_1."
dynamic user2 = new ExpandoObject();
user2.Username = "jzablocki";
user2.Preferences = new ExpandoObject();
user2.Preferences.Theme = "green";
user2.Preferences.TimeZone = "EST";

client.StoreDynamic(StoreMode.Set, "user_2", user2 as ExpandoObject);
var getResult = client.GetDynamic("user_2");
if (getResult.Item1)
{
dynamic item = getResult.Item4;
Console.WriteLine(item.Preferences.Theme);
}

There are alternate approaches toward the dynamic extensions that require casting, because of the limitations of calling an extension method with dynamic arguments. To simplify things, I've stuck with ExpandoObject arguments.
C# obviously isn't a purely dynamic language, and therefore some of the methods are a less terse than they would be in their purely late bound counterparts. However, these methods demonstrate that you don't have to give up the full richness of a schemaless document-oriented database just because your language is statically typed, as long as that language is C# of course...

sglazer -

Yeah, dynamics are a great approach if you don't want to create typed POCOs for every view projection. Let me know how it goes!

-Jeff

0 Answers

No answers yet