Как десериализовать строку JSON в непубличный класс, используя JSON-B?

Я создал три приложения Java 9 Maven с двумя классами для тестирования сериализации и десериализации JSON с использованием JSON-B. Вот код:

package com.jsonbdemos;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;

public class App {

    public static void main(String[] args) {
        Jsonb jsonb = JsonbBuilder.create(new JsonbConfig());
        String jsonData = "{\"creationDate\":\"2018-01-05\"}";

        // Create Widget object from JSON string.
        Widget widget = jsonb.fromJson(jsonData, Widget.class);
        System.out.println("JSON => object: " + widget.toString());

        // Serialize Widget object to JSON string.
        String jsonFromObject = jsonb.toJson(widget);
        System.out.println("object => JSON: " + jsonFromObject);
    }
}

package com.jsonbdemos;
import java.time.LocalDate;

public class Widget { // IllegalAccessException if "public" is removed.
    private LocalDate creationDate;
    public Widget() {}

    @Override
    public String toString() { return "creationDate=" + creationDate; }
    public LocalDate getCreationDate() { return creationDate; }
    public void setCreationDate(LocalDate creationDate) { this.creationDate = creationDate; }
}

Существует зависимость для последней версии эталонной реализации JSON-B ( Eclipse Yasson) в pom.xml:

<dependency>
  <groupId>org.glassfish</groupId>
  <artifactId>javax.json</artifactId>
  <version>[1.1.2,)</version>
</dependency>
<dependency>
  <groupId>javax.json.bind</groupId>
  <artifactId>javax.json.bind-api</artifactId>
  <version>[1.0,)</version>
</dependency>
<dependency>
  <groupId>org.eclipse</groupId>
  <artifactId>yasson</artifactId>
  <version>[1.0.0,)</version>
</dependency>

Приложение работает нормально, но если я изменю уровень доступа класса Widget с общедоступного на ничто (т. Е. "Пакет приватный"), при вызове Jsonb.fromJson() выдается исключение IllegalAccessException:

Исключение в потоке "main" javax.json.bind.JsonbException: не удается создать экземпляр в org.eclipse.yasson.internal.ReflectionUtils.lambda$createNoArgConstructorInstance$1(ReflectionUtils.java:191) в java.base/java.security.AccessController. eclipse.yasson.internal.serializer. Unmarshaller.java:50) в org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:45) в org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:52) в com.jsonbdemos.App.main(App.java:15) Причина : java.lang.IllegalAccessException: класс org.ec lipse.yasson.internal.ReflectionUtils не может получить доступ к члену класса com.jsonbdemos.Widget с модификаторами public в java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361) в java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589) в java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:479) в org.eclipse.yasson.internal.ReflectionUtils.lambg $1(ReflectionUtils.java:189) ... еще 9

Я не вижу в спецификации ничего ( JSR 367: "JSON-B: API Java ™ для привязки JSON") (в разделе 3.7 Java Class), требующего открытый класс для десериализации.

Любые предложения о том, как десериализовать в экземпляр класса, который не является общедоступным с использованием JSON-B?

Обновление (5/2/18):

В JSR 367 говорится, что " любой экземпляр, переданный операции десериализации, должен иметь открытый или защищенный конструктор без аргументов ", но такая же ошибка также возникает, если конструктор является защищенным, а не общедоступным.

Я сообщил об этой проблеме: десериализация все еще не работает с защищенным конструктором без аргументов #118

0 ответов

Я проверил несколько вариантов этого со следующими результатами:

Автономный класс (собственный исходный файл):

  • класс = общедоступный, ctor = общедоступный = УСПЕХ
  • класс = общедоступный, ctor = защищенный = УСПЕХ
  • класс = общедоступный, ctor=pkg-protected = НЕЗАКОННЫЙ ДОСТУП
  • класс = pkg-защищенный, ctor = public = НЕЗАКОННЫЙ ДОСТУП

Статический внутренний класс:

  • класс = общедоступный, ctor = общедоступный = УСПЕХ
  • класс = защищенный, ctor = общедоступный = УСПЕХ
  • класс = pkg-защищенный, ctor = public = НЕЗАКОННЫЙ ДОСТУП
  • класс = общедоступный, ctor = защищенный = УСПЕХ
  • класс = общедоступный, ctor=pkg-protected = НЕЗАКОННЫЙ ДОСТУП

Нестатический внутренний класс:

  • class = public, ctor = public = НЕЗАКОННЫЙ ДОСТУП

Ключевые моменты из этого:

  1. Публичные и защищенные работы, но защищенные пакетами или менее не работают (и класс, и ctor должны иметь равную или более высокую видимость, чем защищенные).
  2. Статические внутренние классы ведут себя так же, как и автономные классы.
  3. Нестатические внутренние классы недоступны, потому что для их создания требуется экземпляр внешнего класса.
Другие вопросы по тегам