3

我编写了一个生成元组列表的 DAML 模型,例如[(Int, Text)]. 我通过 DA Ledger API 接收这些数据 - 如何将其转换为List<Pair<Long, String>>Java?

4

2 回答 2

7

Java 取决于您使用的是原始编译的 Protobuf 类型,还是 Java 语言绑定提供的包装类型。

API 返回的对象使用三种主要类型表示:

  • Record
  • RecordField
  • Value.

稍微简化一下, aRecord是 的列表RecordField, aRecordField是标签, aValue和 aValue可以是许多事物之一,包括 a Int64、 a String、 aRecord或 a List。像这样的元组(Int, Text)在 DAML 中具有特殊符号,但Record在 API 中表示为普通对象。

假设您正在使用从 protobuf 定义编译的类型,并且已经掌握了com.digitalasset.ledger.api.v1.ValueOuterClass.Value表示 的[(Int, Text)],您需要执行以下操作:

  1. 使用Value::getListandValueOuterClass.List::getElementsList将. Value_List<Value>
  2. 通过解开Value列表中的Value::getRecord每一个来获得一个List<Record>
  3. Record::getFields使用get提取每条记录的两个字段List<Pair<RecordField, RecordField>>
  4. RecordFields从with中提取值RecordFields::getValue,给出List<Pair<Value, Value>>
  5. 从对象中提取, 和Int64的别名,得到最终的longStringValueList<Pair<Long, String>>

步骤 2. - 4. 可以使用 Java 的流接口巧妙地完成。显示的代码适用于原始 gRPC 类型,从 a 开始com.digitalasset.ledger.api.v1.ValueOuterClass.Value

import com.digitalasset.ledger.api.v1.ValueOuterClass;
import static java.util.AbstractMap.SimpleImmutableEntry;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Demo {
    static SimpleImmutableEntry<ValueOuterClass.RecordField, ValueOuterClass.RecordField> EntryFromTuple(ValueOuterClass.Record tupleRecord) {
        return new SimpleImmutableEntry<>(tupleRecord.getFields(0), tupleRecord.getFields(1));
    }

    static class SimpleImmutableEntryMap<S, T, U, V> implements Function<SimpleImmutableEntry<S, T>, SimpleImmutableEntry<U, V>> {
        Function<S, U> mapFst;
        Function<T, V> mapSnd;

        public SimpleImmutableEntryMap(Function<S, U> mapFst, Function<T, V> mapSnd) {
            this.mapFst = mapFst;
            this.mapSnd = mapSnd;
        }

        @Override
        public SimpleImmutableEntry<U, V> apply(SimpleImmutableEntry<S, T> stEntry) {
            return new SimpleImmutableEntry<> (mapFst.apply(stEntry.getKey()), mapSnd.apply(stEntry.getValue()));
        }
    }

    static List<SimpleImmutableEntry<Long, String>> mapTuple(ValueOuterClass.Value v) {
        return v.getList().getElementsList().stream()
                .map(ValueOuterClass.Value::getRecord)
                .map(Demo::EntryFromTuple)
                .map(new SimpleImmutableEntryMap<>(ValueOuterClass.RecordField::getValue, ValueOuterClass.RecordField::getValue))
                .map(new SimpleImmutableEntryMap<>(ValueOuterClass.Value::getInt64, ValueOuterClass.Value::getText))
                .collect(Collectors.toList());
    }
}
于 2018-12-13T16:59:19.183 回答
5

假设您有以下 daml 模板:

template ListOfTuples
  with
    party : Party
    listOfTuples : [(Int, Text)]
  where
    signatory party

com.daml.ledger.javaapi.data.Record使用 java api 转换为 a,您可以List<Pair<Long, String>>通过将列表中的元组也视为Records 来将其转换为 a:

import java.util.List;
import javafx.util.Pair;
import java.util.stream.Collectors;
import com.daml.ledger.javaapi.data.Record;

public void parseListOfTuples(Record record) {

  List<Pair<Long, String>> listOfTuples =
     record.getFields().get(1).getValue().asList().get().getValues().stream()
             .map(t -> {
                 List<Record.Field> tuple = t.asRecord().get().getFields();
                 return new Pair<>(
                         tuple.get(0).getValue().asInt64().get().getValue(),
                         tuple.get(1).getValue().asText().get().getValue());
             })
             .collect(Collectors.toList());
}
于 2018-12-13T18:42:18.993 回答