Search code examples
javajsonlambdaclassnotfoundexceptionprotostuff

Converting object (inclusive lambda) to JSON and vice versa


I'm using protostuff to convert object of my own class to JSON and vice versa. There is java 8 and lambdas. Convert to JSON file like:

LinkedBuffer buffer = LinkedBuffer.allocate(2048);
Schema schema = RuntimeSchema.getSchema(obj.getClass());
boolean numeric = false;
byte[] json = JsonIOUtil.toByteArray(obj, schema, numeric, buffer);
Files.write(file, json);

Convert from JSON to obj:

Schema<MyClass> schema = RuntimeSchema.getSchema(MyClass.class);
Path path = Paths.get("path");
byte[] as = Files.readAllBytes(path);
MyClass mc = schema.newMessage();
JsonIOUtil.mergeFrom(as, mc, schema, false);

And when I'm trying to convert JSON to obj a have an exception:

Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: com.test.Blabla$$Lambda$4/1699679644

I think lambda is a problem. Can I convert classes with it?

Object has a filed:

private final Function<,> name;

Solution

  • Your lambda is a runtime expression and cannot be serialized. It is in fact a method pointer, which is valid in your running code which serializes. What would the receiving code (which de-serializes) do with such a method pointer, pointing to a method in your sending code?

    If your sending code is the same as the receiving code, and the possible values of the lambda expression is a well defined set of different methods you should consider to implement an enum and only serializing the enum value:

    public enum Lambdas
    {
        FIRST( s -> new String()),
        SECOND( s -> s + " ");
    
        private Function<String, String> myLambda;
    
        private Lambdas( Function<String, String> aLambda )
        {
            myLambda = aLambda;
        }
    
        public Function<String, String> getLambda()
        {
            return myLambda;
        }
    }
    

    If your Person now has a member

    private Lambdas myLambda;
    

    (which is serializable) your receiving code can use it like this:

    String result = myLambda.getLambda().apply();