Разбор GrailsView данных постов jsonApi - кто-нибудь из команды grails делает общее решение в jsonViews? - PullRequest
0 голосов
/ 25 января 2019

Grails v3.3.9 / jsonViews v1.2.10

работа над мини-проектом с использованием grailsViews и формата jsonApi.

поэтому представления предоставляют поддержку шаблонов для генерации jsonApi из модели вашего домена, но я не могу найти обратное, которое позволяет вам строить объект (и дерево) домена из данных, которые публикуются / исправляются.

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

по сути, мне пришлось переопределить метод createResource в RestfulController. Для этого нужно взять тело сообщения и проанализировать его.

он погружается в json, находит атрибуты и пытается использовать bindData для этой простой карты атрибутов.

отношения сложнее. Я должен перебрать их и посмотреть, есть ли дети с данными для каждого тега.

Затем мне нужно добавить addTo (для каждой записи, если я смогу найти экземпляр в модели предметной области для добавления в коллекцию. Потеря проблем с этим кодом - но на самом деле это обходится сохранением нового OrgRoleInstance

//works - needs lots of improvement !! overwites, lookups etc
@Override
protected <T extends OrgRoleInstance> T createResource() {
    def instance = super.resource.newInstance()
    RequestFacade requestFacade = getObjectToBind()
    BufferedReader bodyReader = requestFacade.request.getReader()
    long bodyLength = requestFacade.request.getContentLengthLong()

    String jsonBody = bodyReader.text
    //String strippedBackJson = jsonBody.replaceAll("\\s+","")
    JsonSlurper slurper = new JsonSlurper()
    def body = slurper.parseText (jsonBody)
    def data = body.data
    String bodyDataType = body.data.type
    //json views  api seems to show the class starting in lower case - change to uppercase
    String dataType = convertFirstCharToUppercase (bodyDataType)
    Map attributes = body.data.attributes
    Map relationships = body.data.relationships

    //wrap in a try block
    //def jsonClassRef = Class.forName(toToBindString) - https://stackoverflow.com/questions/13215403/finding-a-class-reflectively-by-its-simple-name-alone
    //assume users know what they are doing ! - just sanity check simple name
    String resClassSimpleName = resource.getSimpleName()
    assert dataType == resClassSimpleName



    //needs a custom bindData
    bindData instance, attributes //getObjectToBind()
    //process any relationships and bind these
    relationships.each {tag, value ->
        def dataArray = value.data
        for (item in dataArray) {
            def jsonType = item['type']
            //convert first char to uppercase
            String type = convertFirstCharToUppercase (jsonType)
            def id = Long.parseLong (item['id'])

            //with type and id try and find in existing domain model
            def refEntity
            Class<?> domainClass = domainClassLookupByName (type)
            if (domainClass) {
                refEntity = domainClass.get (id)
            }
            //help cant overwrite foreign key - clone the mag?
            if (refEntity) {
                def prop = convertFirstCharToUppercase(tag)
                instance."addTo$prop" (refEntity)
                //if (refEntity.validate())
                    //refEntity.save (failOnError:true)
            }
            instance

        }

    }

    //bindData instance, relationships //getObjectToBind()
    instance
}

данные записи выглядят так (я довольно распечатал результат действия get на другом конце записи, отредактировал это.

Обратите внимание, что это дефект - но рендеринг jsonapi для типа: делает строчные буквы для типа, а не прописные, как вы и ожидали - мне пришлось это компенсировать)

Я надеялся, что команда Grails, возможно, что-то сделала для этого.

Если нет, я попытаюсь запросить улучшение функции

1 Ответ

0 голосов
/ 25 января 2019

Ну, есть объекты команд, и технически говоря, вы можете использовать объекты Домена в качестве объектов команд. Я не рекомендую использовать доменные объекты в качестве командных объектов за пределами игрушечного приложения, хотя из-за присущих угроз безопасности, поэтому я думаю, что это вроде нет ...

Однако я бы посоветовал вам использовать объекты команд, поскольку они дают вам базовую проверку и документируют API ваших контроллеров. Одно замечание: я обычно стараюсь сохранять объекты команд легкими, не добавляя сервисы и не совершая вызовы, по тем же причинам, по которым вы не делаете это в доменах, потребление памяти и вызовы БД относятся к сервисам в переходах. Также я обычно передаю параметры из командного объекта в «красиво» выложенный API, если только объекты команды не представляют, документ Jon, где это будет ovekill.

Существует также командный плагин, который дает объектам команд, больше соглашения о конфигурации, как и другие артефакты Grails. Я написал это, так что вы можете взять это с крошкой соли:)

...