芭蕾舞女演员“类型'json'不支持分配的字段访问”

问题描述

我正在使用Ballerina语言按照here中的指示为在线零售商店中的订单管理创建RESTful Web服务。在处理HTTP PUT请求的资源函数中,有一段代码将从json映射对象(当前用于存储订单,尚未连接数据库)中检索相关订单,并使用来更新其某些字段。 HTTP PUT请求收到的json对象中的内容

我已经声明了json地图对象ordersMap。

map<json> ordersMap = {};

处理PUT请求的资源函数具有如下代码段:

// Get the json obejct from the payload
var updatedOrder = <@untained> req.getJsonPayload();

// Get the existing order that is required by the request from the json map object.
json existingOrder = ordersMap[orderId];

// Updating the necessaries and saving it in the map object.
existingOrder.Order.Name = updatedOrder.Order.Name;
existingOrder.Order.Description = updatedOrder.Order.Description;
ordersMap[orderId] = existingOrder;

当我尝试编译程序时,编译器会引发以下错误

无效操作:键入“ json”不支持分配的字段访问

我一直在网上寻找解决方案,但找不到任何东西。 我正在使用芭蕾舞女演员1.2.4

解决方法

这是因为当您使用json数据类型时,编译器无法保证您所访问的字段存在,并且(如果不存在,则无法计算出要插入相关条目的类型)。

当您想对一段json数据进行操作,并且知道此json结构的形状时,创建相关类型并对其进行操作是个好主意,如果您想要json,则可以将其转换回到json。不幸的是,在Ballerina 1.2.x中没有直接的方法可以从json转换(和转换),如果您可以切换到Ballerina Swanlake轨道,则可以使用以下代码。

import ballerina/io;

type Info record {
    User user;
};

type User record {
    string name;
    string bal_version;
};


public function main() returns error? {
    json j = { user: { name: "Hiran",bal_version: "1.2.4"}};
    json k = { user: { name: "Hiran-New",bal_version: "1.2.4"}};
    io:println(j);
    // Convert json to expected datatype.
    Info|error info = j.fromJsonWithType(Info);
    if (info is Info) {
        Info kInfo = check k.fromJsonWithType(Info);
        info.user.name = kInfo.user.name;

        // convert back to json
        json newJ = info.toJson();
        io:println(newJ);
    } else {
        // Expected json schema did not match.
        // Handle the error here.
    }
}

在芭蕾舞女演员1.2.x中

import ballerina/io;

public function main() returns error? {
    json j = { user: { name: "Hiran",bal_version: "1.2.4"}};
    io:println(j);

    map<json> mj = <map<json>> j;
    map<json> user = <map<json>> mj.get("user");

    user["name"] = <string> k.user.name;
    // note,we update the original json value.
    io:println(j);
}

第二种方法的一个大问题是,如果传入的json值的结构与我们预期的不同,则会因类型转换错误而导致恐慌。

,

如果您使用的是Ballerina 1.2.4,我强烈建议您更新到最新的Ballerina 1.2.x版本(当前是1.2.8,更快是1.2.9)。它们是向后兼容的。因此,更新应该没有任何问题。

谈到您的问题,您可以使用.运算符来访问JSON中的字段。看下面的例子。

如果知道结构的确切形状,则可以使用定义的record类型。然后,您可以使用constructFrom()函数构造记录。否则,您也可以使用.运算符访问字段。

在这两种情况下,请确保相应地处理该错误。我使用checkpanic只是为了显示功能,但是您可以更好地处理它。

import ballerina/io;

type Address record {
    string no;
    string street;
    string city;
};

type Person record {
    string name;
    Address address;
};

public function main() {
    json j = getJson();
    Person p = checkpanic Person.constructFrom(j);
    io:print("Person Record: ");
    io:println(p);

    json address = checkpanic j.address;
    io:print("Address field from JSON: ");
    io:println(address);
}

function getJson() returns json {
    json j = {
        name: "Sherlock",address: {
            no: "221/B",street: "Baker Street",city: "London"
        }
    };
    return j;
}

这将打印以下内容:

Person Record: name=Sherlock address=no=221/B street=Baker Street city=London
Address field from JSON: no=221/B street=Baker Street city=London

在Ballerina 1.2.8上进行了尝试。

您可以查看更多examples here