Is my way for parser written properly?
I can add this property to class Zone, but I don't want that anybody
  could access it from outside.


Which 'access' do you have in mind? through JSON (send you a 'fake' direction for zone1,2) or through code?

Either way, I don't think that by not adding it to the Zone class you will improve the security of your solution?

How do you decide on which parser to use when you receive a json string? BTW, your second json string looks wrong to me (the last direction param)


  [{"Caption":"Tab1","IDs":[4,6],"Direction":"1"},{"Caption":"Tab2","IDs":[9]},"Direction":"3"]


Why do you need Zone1 and Zone2? They're identical so why not simply use Zone? Even your ZoneBaseParser creates Zone objects and has no notion of Zone1 or Zone2.

Maybe you have a predefined set of zones (up to 4) and you need an index. Add an index property, if that's the case.

Your question is interesting but, instead of implementing a solution to the current problem (which would involve reflection), I'd focus on rethinking the json format and the classes and remove the problem altogether.

Quick and easy:

[DataContract]  
private class ZoneJson
{
     [DataMember]
     public int ZoneType { get; set; }//could use an enum instead of int
     [DataMember]
     public int ZoneIndex { get; set; }//if a zone index is needed
     [DataMember]
     public string Caption { get; set; }
     [DataMember]
     public IList&lt;int&gt; IDs { get; set; }
     [DataMember]
     public Direction Direction { get; set; }
}


Or, a more generic approach:

[DataContract]  
private class ZoneJson
{
     [DataMember]
     public int ZoneType { get; set; }//could use an enum instead of int
     [DataMember]
     public int ZoneIndex { get; set; }//if a zone index is needed
     [DataMember]
     public string Caption { get; set; }
     [DataMember]
     public IList&lt;int&gt; IDs { get; set; }


     //a json string containing additional params
     //might be set for certain ZoneTypes and it's contents can vary, based on ZoneType
     [DataMember]
     public string JsonParams { get; set; }
}


Next, you can add a Zone3Params class to implement the storage for Zone3 params (direction):

[DataContract]
[KnownType(typeof(Direction))]
public class Zone3ParamsJson : ZoneParamsBase
{        
    [DataMember]
    public Direction Direction { get; set; }
}


and parse any defined zone type like this:

public class ZoneParserBase : IZoneParser&lt;Zone&gt;
{
    public virtual IList&lt;Zone&gt; Parse(string json)
    {
        IList&lt;Zone&gt; zones = new List&lt;Zone&gt;();
        try
        {
            IList&lt;ZoneJson&gt; parsedZones = json.FromJSON&lt;IList&lt;ZoneJson&gt;&gt;();

            foreach (var parsedZone in parsedZones)
            {
                var zone = new Zone
                {
                    //don't forget the index and type
                    ZoneType = parsedZone.ZoneType,
                    Caption = parsedZone.Caption,
                    Contents = new List&lt;Module&gt;()
                };
                foreach (var id in parsedZone.IDs)
                {
                    var module = currentPage.CreateModule(id);
                    zone.Contents.Add(module);
                }
                //parseParams
                if(zone.ZoneType==3)
                {
                    var params = parsedZone.JsonParams.FromJSON&lt;Zone3ParamsJson&gt;();
                    zone.Params = params;//zone.Params would be something like ZoneParamsBase
                }
                zones.Add(zone);
            }

            return zones;
        }
        catch
        {
            return null;
        }
    }
}