Tornadofx REST 客户端

Tornadofx REST client

我按照此处显示的示例进行操作

link

我掌握了窍门,我设法创建了自己的“员工”实体,并且在网上找到了一些虚拟 api 数据来玩。 like this 问题是,tornadofx 抛出空指针错误,我认为这是因为其余响应发送了类似这样的内容

{
"status": "success",
"data": [
    {
        "id": "1",
        "employee_name": "Tiger Nixon",
        "employee_salary": "320800",
        "employee_age": "61",
        "profile_image": ""
    },

但是当我使用 mocky 并仅提供 json 部分时

[
    {
        "id": "1",
        "employee_name": "Tiger Nixon",
        "employee_salary": "320800",
        "employee_age": "61",
        "profile_image": ""
    },...]

一切正常。 我认为响应中的那些附加字段“状态”和“成功”混淆了 tornadofx 的其余客户端,我无法让它工作,无论如何告诉客户端忽略除 json 之外的所有其他字段数据。

所有链接都是有效的,你可以自己试试。

完整的工作示例

    package com.example.demo.view

import javafx.beans.property.SimpleIntegerProperty
import javafx.beans.property.SimpleStringProperty
import javafx.scene.layout.BorderPane
import tornadofx.*
import javax.json.JsonObject


class Employee (id:Int?=null , name: String? = null, age: Int?=null): JsonModel  {
    val idProperty = SimpleIntegerProperty(this, "id")
    var id by idProperty
    val ageProperty = SimpleIntegerProperty(this, "age")
    var age by ageProperty

    val employeeNameProperty = SimpleStringProperty(this, "name", name)
    var name by employeeNameProperty
    override fun updateModel(json: JsonObject) {
        with(json) {
            id = int("id")!!
           age = int("employee_age")!!
            name = string("employee_name")

        }
    }

    override fun toJSON(json: JsonBuilder) {
        with(json) {
            add("id", id)
            add("employee_name", name)
            add("employee_age", age)

        }
    }
}

class PersonEditor : View("Person Editor") {
    override val root = BorderPane()
  val api : Rest by inject()
    var persons = listOf(Employee(1,"John", 44), Employee(2,"Jay", 33)).observable()
    val model = PersonModel(Employee())

    init {
        api.baseURI = "https://run.mocky.io/v3/"
        val response = api.get("f17509ba-2d12-4c56-b441-69ab23302e43")

        println(response.list())
        println(response.list().toModel<Employee>()[0].name)


    //   print( p.get(1))
        with(root) {
            center {
                tableview(response.list().toModel<Employee>()) {
                    column("Id", Employee::idProperty)
                    column("Name", Employee::employeeNameProperty)
                    column("Age", Employee::ageProperty)

                    // Update the person inside the view model on selection change
                    model.rebindOnChange(this) { selectedPerson ->
                        item = selectedPerson ?: Employee()
                    }
                }
            }

            right {
                form {
                    fieldset("Edit person") {
                        field("Id") {
                            textfield(model.id)
                        }
                        field("Name") {
                            textfield(model.name)
                        }
                        field("Age") {
                            textfield(model.age)
                        }
                        button("Save") {
                            enableWhen(model.dirty)
                            action {
                                save()
                            }
                        }
                        button("Reset").action {
                            model.rollback()
                        }
                    }
                }
            }
        }
    }

    private fun save() {
        // Flush changes from the text fields into the model
        model.commit()

        // The edited person is contained in the model
        val person = model.item

        // A real application would persist the person here
        println("Saving ${person.employeeNameProperty} / ${person.ageProperty}")
    }

}
class PersonModel(person: Employee) : ItemViewModel<Employee>(person) {
    val id = bind(Employee::idProperty)
    val name = bind(Employee::employeeNameProperty)
    val age = bind(Employee::ageProperty)
}

如果您替换基础 url 并将请求发送到 http://dummy.restapiexample.com/api/v1/employees,您将收到我正在谈论的错误

您对 mocky return 的调用是一个列表,因此 .list() 工作正常。但是,您对 restapiexample 的调用 return 是一个对象,而不是列表,因此 .list() 不会执行您期望的操作。你可能可以使用这样的东西,虽然我还没有测试过:

response.one().getJsonArray("data").toModel<Employee>()[0].name)

进一步说明:

如果您不熟悉 JSON 的结构,请查看 the JSON homepage 上的图表。

TornadoFX 有两个使用 JSON returns 的便捷函数:.list().one().list() 函数将检查结果是否为 JsonArray。如果是这样,它只是 returns 它。如果它是一个 JsonObject,它会将那个对象包装在一个列表中并且 return 是新列表。

在您的情况下,由于 restapiexample 正在 returning 对象,因此您调用 .list() 的结果是具有单个对象的 JsonArray。它看起来像这样:

[
  {
    "status": "success",
    "data": [...]
  }
]

显然,单个对象不能转换为 Employee,因此取消引用它的任何内容将导致 NullPointerException.

另一方面,.one() 函数将检查响应是否为 JsonObject。如果是,它只是 return 对象。但是,如果响应是 JsonArray,它将从数组中获取第一项,然后 return 该项。