Processing Nullable fields exceptions
getBolted opened this issue · 8 comments
Hi! Thanks a lot for your work for this repo! Faced a problem with mapping to static field in my project: i need to parse two types of frames( config and data). Config contains info about datatypes and length of binary blocks in the data frames.
So, if i got from the config frame, that all ongoing data frames does not have field X, and there is a field in the mapping class public @Bin (type = BinType.BYTE_ARRAY) byte[] X i'll have "can't find value for mapping field [public byte[] X -> null" . Are there any ways processing this exception, except generating new java template class for each case without nullable field X?
Hello
anyway you should provide something as flag that "it is null" on binary level, may be it would be good just make some custom data type and process it, I will make some small example and provide you
I have added some example of custom read-write-mapping processor for fields which can contain nullable byte array. Potentially it is impossible to have just null on binary level because you should provide something to show that it is null so that it is better to improve serializable object to not have null fields or use some more high level frameworks like protobuf which allows to have nulls just out of the box
Thanks a lot for the respond! I've checked your example, but the processing unit becomes too complicated if i follow your code, cause there are several nullable attributes. I'll try to play with protobuf as you advised, or just hardcode through java reflections. Anyway, thanks for the help!
By the way, is there any way to set fixed length of nullableByteArray data type from the example, as it's assigned for bit/byte arrays through bit:1 [4]?
it writes data in format
int length;
if length < 0 then null else byte [length];
so what fixed size for? or do you mean array of nullable byte arrays?
Well, i'll try to illustrate an example on my case study: we have mapping class with @Bin annotations for 6 fields, 3 of them are byte/bit arrays with certain length, and 3 other are possibly nullable with uncertain length. So before parsing data file and mapping it to this class, we've already parsed another file(config), that says to us all necessary info about byte arrays length and the only thing to do is to build correct parsing string expression for JBBPParser and there are several choices to do this in my mind:
1)(As i've tried before writing this issue) Just ignore fields that are said to be null from the config file and do not include them into parsing expression. That case trows an exception, that some field from the mapping class is null. I was trying to proceed it with java reflections or just writing multiple mapping classes for each possibly nullable variable, but it's too shitcode.
2)The second was to implement your custom mapping processor from the example and play with pointers or smth like that, but anyway it's impossible to set 2 or more nullableByteArray fields without setting the exact length of them.
Thereby the main problem of getting an efficient way of parsing such a cases is finding a way of setting certain length of nullableByteArray in a parsing string expression, like we do this for byte arrays or bit arrays ("nullableByteArray:1 [0] b;" for ex)
if you get byte array size from some external source then you can try JBBPExternalValueProvider
class BKlazz {
@Bin(order = 1, type = BinType.BYTE_ARRAY)
byte[] a;
@Bin(order = 2, type = BinType.BYTE_ARRAY)
byte[] b;
@Bin(order = 3, type = BinType.BYTE_ARRAY)
byte[] c;
}
JBBPParser parser = JBBPParser.prepare("byte [$alen] a; byte [$blen] b; byte [$clen] c;");
BKlazz parsed = parser.parse(new byte[] {1,2,3}, null, new JBBPExternalValueProvider() {
@Override
public int provideArraySize(String fieldName,
JBBPNamedNumericFieldMap numericFieldMap,
JBBPCompiledBlock compiledBlock) {
if ("alen".equals(fieldName)) {
return 0;
} else if ("blen".equals(fieldName)) {
return 3;
} else if ("clen".equals(fieldName)) {
return 0;
} else {
throw new IllegalArgumentException("Unknown name: " + fieldName);
}
}
}).mapTo(new BKlazz());
assertArrayEquals(new byte[0], parsed.a);
assertArrayEquals(new byte[]{1,2,3}, parsed.b);
assertArrayEquals(new byte[0], parsed.c);That's it, this suits for my problem perfectly! Thanks a lot for the help!