Почему связанные объекты экранируются при преобразовании в JSON?

#java #json #spring #hibernate #jpa

#java #json #spring #спящий режим #jpa

Вопрос:

У меня есть контроллер Spring MVC, который извлекает некоторые объекты с помощью запроса. У этих объектов есть связанная сущность, которая eagerly извлекается. Однако, когда я использую JSONObject.toString() , он экранирует связанные данные модели:

     {
        "totalRecords": 29,
        "hasErrors": false,
        "data": {
            "regs": [
                {
                    "is_active": 1,
                    "name": "NAR",
                    "modified": "09/14/2020 08:46 AM",
                    "language": "{"name":"English","id":1,"shortcode":"en"}", <--
                    "id": 1,
                },
                {
                    "is_active": 1,
                    "name": "SAR",
                    "modified": "09/14/2020 08:46 AM",
                    "language": "{"name":"English","id":1,"shortcode":"en"}", <--
                    "id": 2,
                }
            ]
        }
    }
  

Значение в language свойстве является экранированным объектом JSON из связанного объекта. Почему это экранируется таким образом? Как мне это предотвратить?

// Сущность Reg

 public class CmsRegions extends CmsModel implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    
    @JsonManagedReference
    @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.DETACH)
    @JoinColumn(name = "language_id", referencedColumnName = "id")
    private SysLanguages language;
}
  

// Язык сущностей

 public class SysLanguages extends Model implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "name")
    private String name;

    
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "language")
    private Set<CmsRegions> regions;
    
}
  

// Контроллер

 ...
   JSONArray objs  = new JSONArray();
   for (CmsRegions region : regions) {
                JSONObject jsonRegion = new JSONObject();
                
                jsonRegion.put("id", region.getId());
                jsonRegion.put("name", region.getName());
                jsonRegion.put("description", region.getDescription());
                jsonRegion.put("language", region.getLanguage());
                objs.put(jsonRegion);
   }

   String response = new JSONObject(payload).toString();

...
  

Payload это просто POJO, который является объектом данных, который мы используем для передачи данных обратно из API.

Почему language происходит экранирование? Есть ли аннотация, которую я пропускаю?

Обновить

Я знаю, что это не JSONObject делает этого, поскольку я создал здесь тестовый пример:

https://repl.it/repls/GlossyScaredLock

Кажется, что это происходит, когда связанная модель сериализуется, затем присоединяется к модели, которая затем сериализуется. Не уверен, как это предотвратить.

Комментарии:

1. вы пробовали: jsonRegion.put(«язык», новый JSONObject(region.getLanguage()))?

2. Какой getLanguage() метод возвращает? Это обычный геттер или в нем есть что-то еще?

Ответ №1:

Это происходит из-за сериализации, есть некоторые символы, которые заменяются для правильного анализа сообщения :

Пробел заменяется на b, перевод формы заменяется на f, Новая строка заменяется на n, возврат каретки заменяется на r, Табуляция заменяется на t, Двойная кавычка заменяется на «, обратная косая черта заменяется на

Вы можете использовать StringEscapeUtils.unescapeJava(stringToUnEscape) из Apache Commons lang, чтобы удалить те, которые экранируются после анализа.