patterncsharpMinor
Is my way for parser written properly?
Viewed 0 times
writtenparserproperlywayfor
Problem
I have zones
I have json string
I have default parser that will create modules according to IDs(4,6 AND 9).
So, in order to parse the above json I'll need some class like
If I'll need to parse Zone3 with json string
```
public class ZoneParserA : ZonePar
public class Zone
{
public string Caption { get; set; }
public IList Contents { get; set; }
}
public class Zone1 : Zone
{
}
public class Zone2 : Zone
{
}
public class Zone3 : Zone
{
public enum Direction
{
Up = 1,
Down = 2,
Left = 3,
Right = 4
}
public Direction Direction { get; set; }
}I have json string
[{"Caption":"Tab1","IDs":[4,6]},{"Caption":"Tab2","IDs":[9]}] that corresponds to the regular zones like Zone1,Zone2{"Caption":"Tab1","IDs":[4,6]} means that the name of this zone is Tab1 and it will contain Modules #4 and #6.I have default parser that will create modules according to IDs(4,6 AND 9).
public interface IZoneParser
{
IList Parse(string json);
}
public abstract class ZoneParserBase : IZoneParser
{
public virtual IList Parse(string json)
{
IList zones = new List();
try
{
IList parsedZones = json.FromJSON>();
foreach (var parsedZone in parsedZones)
{
var zone = new Zone
{
Caption = parsedZone.Caption,
Contents = new List()
};
foreach (var id in parsedZone.IDs)
{
var module = currentPage.CreateModule(id);
zone.Contents.Add(module);
}
zones.Add(zone);
}
return zones;
}
catch
{
return null;
}
}
}So, in order to parse the above json I'll need some class like
[DataContract]
private class ZoneJson
{
[DataMember]
public string Caption { get; set; }
[DataMember]
public IList IDs { get; set; }
}If I'll need to parse Zone3 with json string
[{"Caption":"Tab1","IDs":[4,6],"Direction":"1"},{"Caption":"Tab2","IDs":[9]},"Direction":"3"], so I'll create```
public class ZoneParserA : ZonePar
Solution
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:
Or, a more generic approach:
Next, you can add a Zone3Params class to implement the storage for Zone3 params (direction):
and parse any defined zone type like this:
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 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 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
{
public virtual IList Parse(string json)
{
IList zones = new List();
try
{
IList parsedZones = json.FromJSON>();
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()
};
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();
zone.Params = params;//zone.Params would be something like ZoneParamsBase
}
zones.Add(zone);
}
return zones;
}
catch
{
return null;
}
}
}Code Snippets
[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<int> IDs { get; set; }
[DataMember]
public Direction Direction { get; set; }
}[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<int> 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; }
}[DataContract]
[KnownType(typeof(Direction))]
public class Zone3ParamsJson : ZoneParamsBase
{
[DataMember]
public Direction Direction { get; set; }
}public class ZoneParserBase : IZoneParser<Zone>
{
public virtual IList<Zone> Parse(string json)
{
IList<Zone> zones = new List<Zone>();
try
{
IList<ZoneJson> parsedZones = json.FromJSON<IList<ZoneJson>>();
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<Module>()
};
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<Zone3ParamsJson>();
zone.Params = params;//zone.Params would be something like ZoneParamsBase
}
zones.Add(zone);
}
return zones;
}
catch
{
return null;
}
}
}Context
StackExchange Code Review Q#3392, answer score: 2
Revisions (0)
No revisions yet.