asn.1数据解析java库推荐

    我知道的asn.1数据编解码java库中,有一个开源的,而且可以编解码per/uper格式数据。算是一个很不错的开源库了。这里推荐给java的朋友们,它也不是没有缺点,比如他就没有GeneralizedTime这种日期类型,而且他目前无法实现asn.1文件到java类的自动生成功能,但是这些问题,不妨碍他作为开源界里一个好工具,因为很多工具并不提供per/uper格式的编解码。github地址为:https://github.com/alexvoronov/gcdc-asn1,虽然star只有9颗,但是个人感觉他很好用。

    首先,对于普通的编解码都是支持的,比如ber、der,下面来谈谈个人使用的总结:

    对于asn.1中的choice,sequence,bit string,integer,ia5string,octet string,enumerated都有很好的支持,下面给出几个示例:

    sequence类型asn.1文件定义如下: 

MapData ::=	SEQUENCE {
		msgCnt MsgCount,
		timeStamp MinuteOfTheYear OPTIONAL,
		nodes NodeList,
		-- intersections or road endpoints
		...
}

   对应的java类代码如下:

@Sequence
@HasExtensionMarker
public static class MapData{
	MsgCount msgCount;
	@Asn1Optional
	MinuteOfTheYear timeStamp ;
	NodeList nodes;
	public MapData() {
		this(new MsgCount(), new MinuteOfTheYear(), new NodeList());
	}
	public MapData(MsgCount msgCount,MinuteOfTheYear timeStamp,NodeList nodes) {
		this.msgCount = msgCount;
		this.timeStamp = timeStamp;
		this.nodes = nodes;
	}
	
	public MsgCount getMsgCount() {
		return msgCount;
	}
	
	public MinuteOfTheYear getTimeStamp() {
		return timeStamp;
	}
	
	public NodeList getNodes() {
		return nodes;
	}
	
}

  enum类型的asn.1文件定义如下:

SourceType ::= ENUMERATED {
		unknown(0),
		selfinfo(1),
		v2x(2),
		video(3),
		microwaveRadar(4),
		loop(5),
		lidar(6),
		integrated(7),
		...
}

     对应的java类代码如下所示:

@HasExtensionMarker
public static enum SourceType{
	unknown(0),
	selfinfo(1),
	v2x(2),
	video(3),
	microwaveRadar(4),
	loop(5),
	lidar(6),
	integrated(7);
	
	private int value;
	private SourceType(int value) {this.value = value;}
	public int value() {return value;}
}

      bit string类型的asn.1文件定义如下:

LaneAttributes-Sidewalk ::= BIT STRING { 
	sidewalk-RevocableLane (0),
	bicyleUseAllowed (1),
	isSidewalkFlyOverLane (2),
	walkBikes (3)
} (SIZE (16))

    对应的java类代码如下所示:

@Bitstring
@FixedSize(16)
public static class LaneAttributes_Sidewalk extends Asn1VarSizeBitstring{
	
	public LaneAttributes_Sidewalk(Boolean... coll) {
		this(Arrays.asList(coll));
	}
	
	public LaneAttributes_Sidewalk(Collection<Boolean> coll) {
		super(coll);
	}
	
	protected LaneAttributes_Sidewalk() {
		this(new ArrayList<Boolean>());
	}
	boolean sidewalk_RevocableLane;
	boolean bicyleUseAllowed;
	boolean isSidewalkFlyOverLane;
	boolean walkBikes;
}

 bitstring个数大于列举个数的:

LaneAttributes-Vehicle ::= BIT STRING { 
	isVehicleRevocableLane (0),
	isVehicleFlyOverLane (1),
	hovLaneUseOnly (2),
	restrictedToBusUse (3),
	restrictedToTaxiUse (4),
	restrictedFromPublicUse (5),
	hasIRbeaconCoverage (6),
	permissionOnRequest (7) 
} (SIZE (8,...))

    对应的java类如下所示:

@Bitstring
@FixedSize(8)
@HasExtensionMarker
public static class LaneAttributes_Vehicle{
	boolean isVehicleRevocableLane;
	boolean isVehicleFlyOverLane;
	boolean hovLaneUseOnly;
	boolean restrictedToBusUse;
	boolean restrictedToTaxiUse;
	boolean restrictedFromPublicUse;
	boolean hasIRbeaconCoverage;
	boolean permissionOnRequest;
}

    以上只是简单的列举了几个例子,总得来说,每一个asn.1的类型都可以对应一个java类型,不管是集合sequence of,还是对象sequence,还是枚举enumerated,还是bitstring,还是integer,另外,对于数据范围也有限制,主要是integer类型的,比如INTEGER(0..127),可以通过注解@IntRange(minValue=0,maxValue=127)来标注在java类上实现范围限制。如下所示:

    MsgCount ::= INTEGER (0..127)

@IntRange(minValue = 0,maxValue = 127)
public static class MsgCount extends Asn1Integer{
	public MsgCount() {
		this(0);
	}
	
	public MsgCount(int value) {
		super(value);
	}
}

    集合类型asn.1文件定义如下:

 ParticipantList ::= SEQUENCE (SIZE(1..16)) OF ParticipantData 

    java类代码如下所示:

@SizeRange(minValue = 1,maxValue = 16)
public static class ParticipantList extends Asn1SequenceOf<ParticipantData>{
	public ParticipantList(ParticipantData... coll) {
		this(Arrays.asList(coll));
	}
	
	public ParticipantList(Collection<ParticipantData> coll){
		super(coll);
	}
}

   ==========================补充choice类型的写法===================== 

    这里根据有个朋友的提示,没有choice类型的写法,这里补上,算是疏漏了。

    asn表示:

-- Main message frame
MessageFrame ::= CHOICE {
	bsmFrame 	BSM,
	mapFrame 	MAP,
	rsmFrame 	RSM,
	spatFrame 	SPAT,
	rsiFrame 	RSI,
	...
}

    java代码:

@Choice
@HasExtensionMarker
public class MessageFrame{
	BSM bsmFrame;
	MAP mapFrame;
	RSM rsmFrame;
	SPAT spatFrame;
	RSI rsiFrame;
	
	public MessageFrame() {
		this(new BSM());
	}
	
	public MessageFrame(BSM bsmFrame) {
		this.bsmFrame = bsmFrame;
	}
	
	public MessageFrame(MAP mapFrame) {
		this.mapFrame = mapFrame;
	}
	
	public MessageFrame(RSM rsmFrame) {
		this.rsmFrame = rsmFrame;
	}
	
	public MessageFrame(SPAT spatFrame) {
		this.spatFrame = spatFrame;
	}
	
	public MessageFrame(RSI rsiFrame) {
		this.rsiFrame = rsiFrame;
	}
	
	public BSM getBsmFrame() {
		return bsmFrame;
	}
	
	public MAP getMapFrame() {
		return mapFrame;
	}
	
	public RSM getRsmFrame() {
		return rsmFrame;
	}
	
	public SPAT getSpatFrame() {
		return spatFrame;
	}
	
	public RSI getRsiFrame() {
		return rsiFrame;
	}
	
	public boolean hasBsmFrame() {
		return this.bsmFrame != null;
	}
	
	public boolean hasMapFrame() {
		return this.mapFrame != null;
	}
	
	public boolean hasRsmFrame() {
		return this.rsmFrame != null;
	}
	
	public boolean hasSpatFrame() {
		return this.spatFrame != null;
	}
	
	public boolean hasRsiFrame() {
		return this.rsiFrame != null;
	}
}

    octet string类型asn1表示:

id OCTET STRING (SIZE(8))

     java代码:

@OctetString
@FixedSize(8)
public class OctetID extends Asn1SequenceOf<Byte>{
	public OctetID() {
		this(new byte[] {0});
	}
	public OctetID(byte... coll) {
		this(boxed(coll));
	}
	
	public OctetID(Byte... coll) {
		this(Arrays.asList(coll));
	}
	
	public OctetID(Collection<Byte> coll) {
		super(coll);
	}
	private static Byte[] boxed(byte... coll) {
		Byte[] boxedArray = new Byte[coll.length];
		for (int i = 0; i < coll.length; i++) {
			boxedArray[i] = coll[i];
		}
		return boxedArray;
	}
}

    在asn.1表示中,如果有(...)表示还有扩展,在java类上,就需要加上注解:@HasExtensionMarker。

    在使用的时候,如果是需要per/uper编解码,我们直接使用UperEncode.encode(Object obj),或者UperEncode.decode(byte[] data,Class<T> t) 来分别进行编码和解码。

    需要说明的是,数据的范围,比如(0...127)明确表示范围从0-127,这个一定要在java类上通过注解@IntRange()表示清楚,而且不能省略,否则会出错,再一个就是如果asn.1表式中有...,在java类上,一定要通过@HasExtenstionMarker标注出来,否则,也会因为范围问题而出现意想不到的错误,集合的长度也有明确的限制,比如SIZE(1..16),就是表示集合长度在最小值1,最大值16之间,需要通过@SizeRange()标注出来。

    还有一个OPTIONAL修饰符,表示字段可有可无,可选的,我们在定义java类的时候,对其属性一定要使用@Asn1Optional注解标注。

    再一个需要注意的地方是,很多java类,都需要定义好几个构造函数,基本需要一个无参构造函数和一个全部参数的构造函数,因为在进行解码的时候,肯定需要通过反射来进行生成对应的类的,如果对应的构造函数缺失,极有可能运行的时候报错。

    以前写过一个博客,介绍过asnlab提供的一个编解码框架,他能根据asn.1文件生成java代码,而且还可以与eclipse集成,但是有个缺点就是他提供一个免费试用的机会,只有一个月的license,一个月一过,就无法使用了。功能倒是很齐全,per/uper也都支持,唯独不是免费的,一年的费用好像就是6000RMB,如果没有特别的需要,觉着还是免费的比较好。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值