0

this is a kind of data i have to de-serialize

{
    "id": "M:11427",
    "title": "DAX30",
    "nextStartId": "S:727831",
    "sections": [
        {
            "type": "HIGHLIGHTS",
            "baseResults": [ values of type highlights ],
            "hasMore": true
        },
        {
            "type": "CHART",
            "hasMore": false,
            "chartTypes": [ string values ]
        },
        {
            "type": "TWEETS",
            "baseResults": [ values of type tweets ],
            "hasMore": true
        }]
}

I have to serialize & deserialize them all. I want to create something that can hold the values corresponding to baseResults.

there is a main class that represent the whole json

class Data 
{
...
ObservableCollection<Section> sections{get;set;}
...
}

then there is a class that represents the data in sections array of main json

class Section
{
string type{get;set;}// thi elements decides what kind of data would be in baseResults
dynamic baseResults{get;set;} //it should hold ObservableCollection of either Highlights or Tweets etc.
}

base class for type of data coming in baseResults array is an abstract class class CategoryData and its children are class Highlights & class Tweets

I am using dynamic since I can not assign an ObservableCollection<CategoryData> with ObservableCollection<Highlights>. But I don't want to use this dynamic or object type instead I want something relevant. please suggest me what could be a better approach for this problem.

  • Do you do the serialization&deserialization manually, or do you use some library? – Euphoric Mar 21 '14 at 14:16
  • @Euphoric basically I am using newtonsoft-json library. but for this particular json, i had to do manual de/serialization. – Ankit Mar 21 '14 at 14:34
1

If I'm understanding you correctly, you're trying to find a statically-typed way to say "a value of type Section can be either a value of type Highlights, Chart, or Tweets". There are many terms for this, including tagged union, discriminated union, variant, or sum type but they all refer to the same concept. Sum types are a standard feature in statically-typed functional programming languages, but with a bit of ingenuity you can roll your own in C#. Using that answer as a template, and adding sealed to make sure no one adds any extra subclasses, your Section type would look something like this:

public abstract class Section
{
    // Prevent subclassing outside of this scope
    private Section() {}

    // Subclass implementation calls the appropriate function.
    public abstract R Match<R>(Func<H, R> IfHighlight, Func<C, R> IfChart, Func<T, R> IfTweet);

    // Convenience wrapper for when the caller doesn't want to return a value
    // from the match expression.
    public sealed void Match(Action<H> IfHighlight, Action<C> IfChart, Action<T> IfTweet)
    {
        this.Match<int>(
            IfHighlight: Section => { IfHighlight(Section); return 0; },
            IfChart: Section => { IfChart(Section); return 0; },
            IfTweet: Section => { IfTweet(Section); return 0; }
        );
    }

    // From here on down, you define your specific types as usual, and override Match to call
    // the correct function

    public sealed class Highlight : Section
    {
        // Implementation goes here

        public override R Match<R>(Func<H, R> IfHighlight, Func<C, R> IfChart, Func<T, R> IfTweet)
        {
            return IfHighlight(this);
        }
    }

    public class Chart : Section
    {
        // Implementation goes here

        public override R Match<R>(Func<H, R> IfHighlight, Func<C, R> IfChart, Func<T, R> IfTweet)
        {
            return IfChart(this);
        }
    }

    public class Tweet : Section
    {
        // Implementation goes here

        public override R Match<R>(Func<H, R> IfHighlight, Func<C, R> IfChart, Func<T, R> IfTweet)
        {
            return IfTweet(this);
        }
    }
}

With that in place, you can declare variables of type Section, and act on them by passing 3 functions to the Match methods:

Section section = deserializeJson()
section.Match(
    IfHighlight: highlight => /* code to use if you get a Highlight */
    IfChart: chart => /* ... */
    IfTweet: tweet => /* ... */
);

You could just as easily have a collection of Sections and operate on them that way when you iterate over it.

|improve this answer|||||
0

How about using generics:

class Section<TCategoryData> where TCategoryData : CategoryData
{
    string type{get;set;}
    ObservableCollection<TCategoryData> baseResults{get;set;}
}


class HighlightSection : Section<Highlights> {}

class TweetSection : Section<Tweets> {}
|improve this answer|||||
  • this would not work, as I have to decide which class to instantiate based on type which is a member of Section itself. – Ankit Mar 21 '14 at 12:50
  • So how do you expect it to be statically typed? – Uri Agassi Mar 21 '14 at 12:58
  • I was looking for something equivalent of wildcard of java however I don't think its possible, but is there no better way to handle it or would u suggest having ObservableCollection<object> is the only better possible way? – Ankit Mar 21 '14 at 13:02
  • You mean ObservableObject<CategoryData>? Yes, and I believe it will be as good as wildcards is this (read only) use case – Uri Agassi Mar 21 '14 at 14:00
0

You are supposed to choose concrete subtype of Section BEFORE you create the instance. The type property should not even be in a Section and should be tied to what subclass the instance is.

But how to do this depends on how you are doing the serialization and deserialization.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.