Hyperledger fabric 要将JSON格式的数据文件上载到Hyperledger Composer资产注册表中

Hyperledger fabric 要将JSON格式的数据文件上载到Hyperledger Composer资产注册表中,hyperledger-fabric,hyperledger-composer,Hyperledger Fabric,Hyperledger Composer,出于开发/测试目的,我配置了一个单独的事务(使用在线游乐场)来为定义的参与者上传一些主记录。接下来,我想构建一个特性来演示这些记录实际上可以从遗留应用程序中提取并导入到资产/参与者注册表中 我已经使用在线可用的转换器之一将提取的(.csv格式)数据文件转换为.json格式文件 有人建议我应该利用RESTAPI来构建这段代码。有没有人能告诉我相关的文档、读取几百条(JSON格式)记录并将其发布到参与者/资产注册表的示例代码 谢谢 JSON必须符合Composer所期望的格式—特别是它必须具有$cl

出于开发/测试目的,我配置了一个单独的事务(使用在线游乐场)来为定义的参与者上传一些主记录。接下来,我想构建一个特性来演示这些记录实际上可以从遗留应用程序中提取并导入到资产/参与者注册表中

我已经使用在线可用的转换器之一将提取的(.csv格式)数据文件转换为.json格式文件

有人建议我应该利用RESTAPI来构建这段代码。有没有人能告诉我相关的文档、读取几百条(JSON格式)记录并将其发布到参与者/资产注册表的示例代码


谢谢

JSON必须符合Composer所期望的格式—特别是它必须具有$class属性以指示类型信息


如果您的数据是预期的格式,那么您可以通过向composer rest服务器发送HTTP POST来创建资产(例如,使用bash和curl),或者,您可以使用Node.js SDK创建一个命令行应用程序,该应用程序从磁盘读取JSON文件,然后使用asset registry API创建资产。

JSON必须符合Composer所期望的格式,特别是它必须具有$class属性以指示类型信息


如果您的数据是预期格式,那么您可以通过向composer rest服务器发送HTTP POST来创建资产(例如,使用bash和curl),或者您可以使用Node.js SDK创建一个命令行应用程序,从磁盘读取JSON文件,然后使用asset registry API创建资产。

当然,事实上,我刚刚为我正在编写的区块链教程完成了这项工作。入站数据的结构用于识别参与者和资产。在我的示例中,有5种类型的参与者和1种类型的资产。该代码将处理多种类型的资产。入站文件是使用JSON表示法的文本文件:

{ "members":
    [
        {"type": "Seller", "pw": "bob", "companyName": "PC Hardware, Inc", "id": "bob@pchardwareinc.com"},
        {"type": "Seller", "pw": "jojo", "companyName": "Inovative Solutions, Inc", "id": "jojo@innovativesolutionsinc.com"},
        {"type": "Seller", "pw": "mary", "companyName": "The i-Series Experts, Inc", "id": "mary@iseriesexpertsinc.com"},
        {"type": "Seller", "pw": "wilber", "companyName": "Cooling Systems R Us, Inc", "id": "wilber@coolingsystemsrusinc.com"},
        {"type": "Seller", "pw": "erin", "companyName": "2nd Life Systems, Inc", "id": "Erin@2ndlifesystemsinc.com"},
        {"type": "Seller", "pw": "abdul", "companyName": "The Cognitive Advantage, Inc", "id": "abdul@cognitiveadvantageinc.com"},
        {"type": "Seller", "pw": "aiesha", "companyName": "Cloud Nine Software, Inc", "id": "aiesha@cloudninesoftwareinc.com"},
        {"type": "Seller", "pw": "joshua", "companyName": "Office Experts, Inc", "id": "joshua@officeexpertsinc.com"},
        {"type": "Seller", "pw": "alwayson", "companyName": "NonStop, Inc", "id": "alwayson@nonstopinc.com"},
        {"type": "Seller", "pw": "anytime", "companyName": "Virtual Paper, Inc", "id": "anytime@virtualpaperinc.com"},
        {"type": "Buyer", "pw": "yes", "companyName": "Software Solutions, Inc", "id": "yes@softwaresolutionsinc.com"},
        {"type": "Buyer", "pw": "buyer1", "companyName": "Hybrid Cloud Designs, Inc", "id": "buyer1@hybridclouddesignsinc.com"},
        {"type": "Buyer", "pw": "eric", "companyName": "Born On The Cloud, Inc", "id": "eric@bornonthecloudinc.com"},
        {"type": "Buyer", "pw": "abby", "companyName": "Kid Friendly Learning, Inc", "id": "abby@kidfriendlyinc.com"},
        {"type": "Buyer", "pw": "kristen", "companyName": "The Education Game, Inc", "id": "kristen@gameify.com"},
        {"type": "Shipper", "pw": "speedmatters", "companyName": "Fast Eddy, Inc", "id": "speedmatters@fasteddyinc.com"},
        {"type": "Shipper", "pw": "wantitnow", "companyName": "The Overnight Experts, Inc", "id": "wantitnow@overnightexpressinc.com"},
        {"type": "Provider", "pw": "info", "companyName": "PC Hardware Now, Inc", "id": "info@pchardwarenowinc.com"},
        {"type": "Provider", "pw": "power", "companyName": "UPS Systems, Inc", "id": "power@upssystemsinc.com"},
        {"type": "Provider", "pw": "online", "companyName": "The App Store, Inc", "id": "online@theappstoreinc.com"},
        {"type": "FinanceCo", "pw": "easymoney", "companyName": "The Global Financier", "id": "easymoney@easymoneyinc.com"}
    ],
    "items":
    [
        {"itemNo": 1, "itemDescription": "Macbook Pro 16Gb, 1Tb", "quantity": 2000, "unitPrice": 1285},
        {"itemNo": 2, "itemDescription": "Macbook Pro 8Gb, .5Tb", "quantity": 2000, "unitPrice": 985},
        {"itemNo": 3, "itemDescription": "Lenovo Thinkpad W520 16Gb, .25Tb", "quantity": 1000, "unitPrice": 500},
        {"itemNo": 4, "itemDescription": "Lenovo Thinkpad W520 32Gb, 1Tb", "quantity": 4000, "unitPrice": 1565},
        {"itemNo": 5, "itemDescription": "4K Monitor - 25", "quantity": 4000, "unitPrice": 265},
        {"itemNo": 6, "itemDescription": "4K Monitor - 32", "quantity": 4000, "unitPrice": 365},
        {"itemNo": 7, "itemDescription": "4K Monitor - 37", "quantity": 4000, "unitPrice": 465},
        {"itemNo": 8, "itemDescription": "4K Monitor - 42", "quantity": 4000, "unitPrice": 565}
    ],
    "assets":
    [   
        {"type": "Order", "id": "001", "buyer": "yes@softwaresolutionsinc.com", "seller": "bob@pchardwareinc.com", "items": [{"itemNo": 1, "quantity": 5}, {"itemNo": 2, "quantity": 2}, {"itemNo": 6, "quantity": 2}] },
        {"type": "Order", "id": "002", "buyer": "yes@softwaresolutionsinc.com", "seller": "jojo@innovativesolutionsinc.com", "items": [{"itemNo": 2, "quantity": 5}, {"itemNo": 8, "quantity": 2}] },
        {"type": "Order", "id": "003", "buyer": "yes@softwaresolutionsinc.com", "seller": "Erin@2ndlifesystemsinc.com", "items": [{"itemNo": 3, "quantity": 15}, {"itemNo": 4, "quantity": 20}] },
        {"type": "Order", "id": "004", "buyer": "yes@softwaresolutionsinc.com", "seller": "aiesha@cloudninesoftwareinc.com", "items": [{"itemNo": 1, "quantity": 5}, {"itemNo": 2, "quantity": 2}, {"itemNo": 6, "quantity": 2}] },
        {"type": "Order", "id": "005", "buyer": "yes@softwaresolutionsinc.com", "seller": "joshua@officeexpertsinc.com", "items": [{"itemNo": 2, "quantity": 5}, {"itemNo": 8, "quantity": 2}] },
        {"type": "Order", "id": "006", "buyer": "eric@bornonthecloudinc.com", "seller": "Erin@2ndlifesystemsinc.com", "items": [{"itemNo": 3, "quantity": 15}, {"itemNo": 4, "quantity": 20}] },
        {"type": "Order", "id": "007", "buyer": "eric@bornonthecloudinc.com", "seller": "bob@pchardwareinc.com", "items": [{"itemNo": 1, "quantity": 5}, {"itemNo": 2, "quantity": 2}, {"itemNo": 6, "quantity": 2}] },
        {"type": "Order", "id": "008", "buyer": "eric@bornonthecloudinc.com", "seller": "jojo@innovativesolutionsinc.com", "items": [{"itemNo": 2, "quantity": 5}, {"itemNo": 8, "quantity": 2}] },
        {"type": "Order", "id": "009", "buyer": "eric@bornonthecloudinc.com", "seller": "Erin@2ndlifesystemsinc.com", "items": [{"itemNo": 3, "quantity": 15}, {"itemNo": 4, "quantity": 20}] }
    ]
}
然后,我打开一个管理员连接并遍历成员(参与者)和资产。我已经包含了代码段的第一部分,它遍历成员并将它们添加到相应的注册表中,然后为它们创建一个标识。对资产执行此操作的代码类似。您将注意到,在标识过程中,成员id和机密会写入本地文件。这对于生产系统来说是一个糟糕的想法,但会使教程更易于管理。很明显,你需要以不同的方式处理身份创建问题

exports.autoLoad = function(req, res, next) {
    // get the autoload file
    let newFile = path.join(path.dirname(require.main.filename),'startup','memberList.json');
    let startupFile = JSON.parse(fs.readFileSync(newFile));
    // connect to the network
    let businessNetworkConnection;
    let factory;
    let adminConnection = new AdminConnection();
        adminConnection.connect(config.composer.connectionProfile, config.composer.adminID, config.composer.adminPW)
        .then(() => {
            businessNetworkConnection = new BusinessNetworkConnection();
            return businessNetworkConnection.connect(config.composer.connectionProfile, network, adminID, adminPW)
            .then(() => {
                factory = businessNetworkConnection.getBusinessNetwork().getFactory();
                for (let each in startupFile.members)
                    {(function(_idx, _arr)
                        {
                            return businessNetworkConnection.getParticipantRegistry(NS+'.'+_arr[_idx].type)
                            .then(function(participantRegistry){
                                return participantRegistry.get(_arr[_idx].id)
                                .then((_res) => {console.log('['+_idx+'] member with id: '+_arr[_idx].id+' already exists in Registry '+NS+'.'+_arr[_idx].type)})
                                .catch((error) => {
                                    let participant = factory.newResource(NS, _arr[_idx].type, _arr[_idx].id);
                                    participant.companyName = _arr[_idx].companyName;
                                    participantRegistry.add(participant)
                                    .then(() => {
                                        console.log('['+_idx+'] '+_arr[_idx].companyName+" successfully added");
                                    })
                                    .then(() => {
                                        return businessNetworkConnection.issueIdentity(NS+'.'+_arr[_idx].type+'#'+_arr[_idx].id, _arr[_idx].pw)
                                            .then((result) => {
                                                let _mem = _arr[_idx];
                                                _mem.secret = result.userSecret;
                                                _mem.userID = result.userID;
                                                memberTable.push(_mem);
                                                svc.saveMemberTable(memberTable);
                                            })
                                            .catch((error) => {
                                                console.error('create id for '+_arr[_idx].id+'failed.',error.message);
                                            });
                                        })
                                    .catch((error) => {console.log(_arr[_idx].companyName+" add failed",error);});
                                    });
                                })
                            .catch((error) => {console.log('error with getParticipantRegistry', error)});
                        })(each, startupFile.members)
                    }

这里引用的所有代码都在ZeroToBlockchain教程和git repo的第5章中。该教程仍在开发中,但已完成本节,可在此处获得:

当然,事实上,我刚刚为我正在编写的区块链教程完成了这项工作。入站数据的结构用于识别参与者和资产。在我的示例中,有5种类型的参与者和1种类型的资产。该代码将处理多种类型的资产。入站文件是使用JSON表示法的文本文件:

{ "members":
    [
        {"type": "Seller", "pw": "bob", "companyName": "PC Hardware, Inc", "id": "bob@pchardwareinc.com"},
        {"type": "Seller", "pw": "jojo", "companyName": "Inovative Solutions, Inc", "id": "jojo@innovativesolutionsinc.com"},
        {"type": "Seller", "pw": "mary", "companyName": "The i-Series Experts, Inc", "id": "mary@iseriesexpertsinc.com"},
        {"type": "Seller", "pw": "wilber", "companyName": "Cooling Systems R Us, Inc", "id": "wilber@coolingsystemsrusinc.com"},
        {"type": "Seller", "pw": "erin", "companyName": "2nd Life Systems, Inc", "id": "Erin@2ndlifesystemsinc.com"},
        {"type": "Seller", "pw": "abdul", "companyName": "The Cognitive Advantage, Inc", "id": "abdul@cognitiveadvantageinc.com"},
        {"type": "Seller", "pw": "aiesha", "companyName": "Cloud Nine Software, Inc", "id": "aiesha@cloudninesoftwareinc.com"},
        {"type": "Seller", "pw": "joshua", "companyName": "Office Experts, Inc", "id": "joshua@officeexpertsinc.com"},
        {"type": "Seller", "pw": "alwayson", "companyName": "NonStop, Inc", "id": "alwayson@nonstopinc.com"},
        {"type": "Seller", "pw": "anytime", "companyName": "Virtual Paper, Inc", "id": "anytime@virtualpaperinc.com"},
        {"type": "Buyer", "pw": "yes", "companyName": "Software Solutions, Inc", "id": "yes@softwaresolutionsinc.com"},
        {"type": "Buyer", "pw": "buyer1", "companyName": "Hybrid Cloud Designs, Inc", "id": "buyer1@hybridclouddesignsinc.com"},
        {"type": "Buyer", "pw": "eric", "companyName": "Born On The Cloud, Inc", "id": "eric@bornonthecloudinc.com"},
        {"type": "Buyer", "pw": "abby", "companyName": "Kid Friendly Learning, Inc", "id": "abby@kidfriendlyinc.com"},
        {"type": "Buyer", "pw": "kristen", "companyName": "The Education Game, Inc", "id": "kristen@gameify.com"},
        {"type": "Shipper", "pw": "speedmatters", "companyName": "Fast Eddy, Inc", "id": "speedmatters@fasteddyinc.com"},
        {"type": "Shipper", "pw": "wantitnow", "companyName": "The Overnight Experts, Inc", "id": "wantitnow@overnightexpressinc.com"},
        {"type": "Provider", "pw": "info", "companyName": "PC Hardware Now, Inc", "id": "info@pchardwarenowinc.com"},
        {"type": "Provider", "pw": "power", "companyName": "UPS Systems, Inc", "id": "power@upssystemsinc.com"},
        {"type": "Provider", "pw": "online", "companyName": "The App Store, Inc", "id": "online@theappstoreinc.com"},
        {"type": "FinanceCo", "pw": "easymoney", "companyName": "The Global Financier", "id": "easymoney@easymoneyinc.com"}
    ],
    "items":
    [
        {"itemNo": 1, "itemDescription": "Macbook Pro 16Gb, 1Tb", "quantity": 2000, "unitPrice": 1285},
        {"itemNo": 2, "itemDescription": "Macbook Pro 8Gb, .5Tb", "quantity": 2000, "unitPrice": 985},
        {"itemNo": 3, "itemDescription": "Lenovo Thinkpad W520 16Gb, .25Tb", "quantity": 1000, "unitPrice": 500},
        {"itemNo": 4, "itemDescription": "Lenovo Thinkpad W520 32Gb, 1Tb", "quantity": 4000, "unitPrice": 1565},
        {"itemNo": 5, "itemDescription": "4K Monitor - 25", "quantity": 4000, "unitPrice": 265},
        {"itemNo": 6, "itemDescription": "4K Monitor - 32", "quantity": 4000, "unitPrice": 365},
        {"itemNo": 7, "itemDescription": "4K Monitor - 37", "quantity": 4000, "unitPrice": 465},
        {"itemNo": 8, "itemDescription": "4K Monitor - 42", "quantity": 4000, "unitPrice": 565}
    ],
    "assets":
    [   
        {"type": "Order", "id": "001", "buyer": "yes@softwaresolutionsinc.com", "seller": "bob@pchardwareinc.com", "items": [{"itemNo": 1, "quantity": 5}, {"itemNo": 2, "quantity": 2}, {"itemNo": 6, "quantity": 2}] },
        {"type": "Order", "id": "002", "buyer": "yes@softwaresolutionsinc.com", "seller": "jojo@innovativesolutionsinc.com", "items": [{"itemNo": 2, "quantity": 5}, {"itemNo": 8, "quantity": 2}] },
        {"type": "Order", "id": "003", "buyer": "yes@softwaresolutionsinc.com", "seller": "Erin@2ndlifesystemsinc.com", "items": [{"itemNo": 3, "quantity": 15}, {"itemNo": 4, "quantity": 20}] },
        {"type": "Order", "id": "004", "buyer": "yes@softwaresolutionsinc.com", "seller": "aiesha@cloudninesoftwareinc.com", "items": [{"itemNo": 1, "quantity": 5}, {"itemNo": 2, "quantity": 2}, {"itemNo": 6, "quantity": 2}] },
        {"type": "Order", "id": "005", "buyer": "yes@softwaresolutionsinc.com", "seller": "joshua@officeexpertsinc.com", "items": [{"itemNo": 2, "quantity": 5}, {"itemNo": 8, "quantity": 2}] },
        {"type": "Order", "id": "006", "buyer": "eric@bornonthecloudinc.com", "seller": "Erin@2ndlifesystemsinc.com", "items": [{"itemNo": 3, "quantity": 15}, {"itemNo": 4, "quantity": 20}] },
        {"type": "Order", "id": "007", "buyer": "eric@bornonthecloudinc.com", "seller": "bob@pchardwareinc.com", "items": [{"itemNo": 1, "quantity": 5}, {"itemNo": 2, "quantity": 2}, {"itemNo": 6, "quantity": 2}] },
        {"type": "Order", "id": "008", "buyer": "eric@bornonthecloudinc.com", "seller": "jojo@innovativesolutionsinc.com", "items": [{"itemNo": 2, "quantity": 5}, {"itemNo": 8, "quantity": 2}] },
        {"type": "Order", "id": "009", "buyer": "eric@bornonthecloudinc.com", "seller": "Erin@2ndlifesystemsinc.com", "items": [{"itemNo": 3, "quantity": 15}, {"itemNo": 4, "quantity": 20}] }
    ]
}
然后,我打开一个管理员连接并遍历成员(参与者)和资产。我已经包含了代码段的第一部分,它遍历成员并将它们添加到相应的注册表中,然后为它们创建一个标识。对资产执行此操作的代码类似。您将注意到,在标识过程中,成员id和机密会写入本地文件。这对于生产系统来说是一个糟糕的想法,但会使教程更易于管理。很明显,你需要以不同的方式处理身份创建问题

exports.autoLoad = function(req, res, next) {
    // get the autoload file
    let newFile = path.join(path.dirname(require.main.filename),'startup','memberList.json');
    let startupFile = JSON.parse(fs.readFileSync(newFile));
    // connect to the network
    let businessNetworkConnection;
    let factory;
    let adminConnection = new AdminConnection();
        adminConnection.connect(config.composer.connectionProfile, config.composer.adminID, config.composer.adminPW)
        .then(() => {
            businessNetworkConnection = new BusinessNetworkConnection();
            return businessNetworkConnection.connect(config.composer.connectionProfile, network, adminID, adminPW)
            .then(() => {
                factory = businessNetworkConnection.getBusinessNetwork().getFactory();
                for (let each in startupFile.members)
                    {(function(_idx, _arr)
                        {
                            return businessNetworkConnection.getParticipantRegistry(NS+'.'+_arr[_idx].type)
                            .then(function(participantRegistry){
                                return participantRegistry.get(_arr[_idx].id)
                                .then((_res) => {console.log('['+_idx+'] member with id: '+_arr[_idx].id+' already exists in Registry '+NS+'.'+_arr[_idx].type)})
                                .catch((error) => {
                                    let participant = factory.newResource(NS, _arr[_idx].type, _arr[_idx].id);
                                    participant.companyName = _arr[_idx].companyName;
                                    participantRegistry.add(participant)
                                    .then(() => {
                                        console.log('['+_idx+'] '+_arr[_idx].companyName+" successfully added");
                                    })
                                    .then(() => {
                                        return businessNetworkConnection.issueIdentity(NS+'.'+_arr[_idx].type+'#'+_arr[_idx].id, _arr[_idx].pw)
                                            .then((result) => {
                                                let _mem = _arr[_idx];
                                                _mem.secret = result.userSecret;
                                                _mem.userID = result.userID;
                                                memberTable.push(_mem);
                                                svc.saveMemberTable(memberTable);
                                            })
                                            .catch((error) => {
                                                console.error('create id for '+_arr[_idx].id+'failed.',error.message);
                                            });
                                        })
                                    .catch((error) => {console.log(_arr[_idx].companyName+" add failed",error);});
                                    });
                                })
                            .catch((error) => {console.log('error with getParticipantRegistry', error)});
                        })(each, startupFile.members)
                    }

这里引用的所有代码都在ZeroToBlockchain教程和git repo的第5章中。本教程仍在开发中,但已通过本节完成,可在此处获得:

谢谢Dan!我将如何构造包含患者主数据的JSON文件-pl。请参见下面的两个示例记录:[{“PersonID”:“Patient-011”,“Title”:“Mr”,“Firstname”:“John”,“Lastname”:“Doe”,“DoB”:“1-Jan-50”,},{“PersonID”:“Patient-012”,“Role”:“Patient”,“Title”:“Mr”,“Firstname”:“Donny”,“Lastname”:“Trumpf”,“DoB”:“45年3月1日”}]感谢Dan的指导-我的批量上传脚本昨天运行良好!谢谢你,丹!我将如何构造包含患者主数据的JSON文件-pl。请参见下面的两个示例记录:[{“PersonID”:“Patient-011”,“Title”:“Mr”,“Firstname”:“John”,“Lastname”:“Doe”,“DoB”:“1-Jan-50”,},{“PersonID”:“Patient-012”,“Role”:“Patient”,“Title”:“Mr”,“Firstname”:“Donny”,“Lastname”:“Trumpf”,“DoB”:“45年3月1日”}]感谢Dan的指导-我的批量上传脚本昨天运行良好!非常感谢鲍勃!!!我走上了丹建议的道路,取得了不错的进步(按照我自己的标准…:-()但是您提供的文档/示例代码应该会给我巨大的推动,使我能够完成我即将构建的概念验证的这个组件!!!再次非常感谢,干杯!Udayanudayudayan-不客气。让我知道这个答案是否足够,或者您是否需要更多帮助。事实上!我昨天完成了我的脚本,它工作正常It’太美了!!非常感谢Bob!!!我已经沿着Dan建议的道路开始了,并且取得了不错的进步(按照我自己的标准…:-()但是您提供的文档/示例代码应该会给我巨大的推动,使我能够完成我即将构建的概念验证的这个组件!!!再次非常感谢,干杯!Udayanudayudayan-不客气。让我知道这个答案是否足够,或者您是否需要更多帮助。事实上!我昨天完成了我的脚本,它工作正常太美了!!