Как преобразовать кортежи DAML, полученные через API DA Ledger, в пары Java?
Я написал модель DAML, которая генерирует список кортежей, например [(Int, Text)]
, Я получаю эти данные через API DA Ledger - как мне преобразовать их в List<Pair<Long, String>>
в Java?
2 ответа
Java зависит от того, работаете ли вы с необработанными скомпилированными типами Protobuf или с обернутыми типами, предоставляемыми привязками языка Java.
Объекты, возвращаемые API, представлены тремя основными типами:
Record
RecordField
Value
,
Упрощая несколько,Record
это список RecordField
, RecordField
это ярлык и Value
и Value
может быть одной из многих вещей, в том числе Int64
, String
, Record
или List
, Кортежи как (Int, Text)
имеют специальные обозначения в DAML, но представлены как нормальные Record
объекты в API.
Предполагая, что вы используете типы, скомпилированные из определений protobuf, и получили в свои руки com.digitalasset.ledger.api.v1.ValueOuterClass.Value
представляя [(Int, Text)]
Вам необходимо сделать следующее:
- использование
Value::getList
а такжеValueOuterClass.List::getElementsList
развернутьValue
вList<Value>
, - Развернуть каждый
Value
в списке черезValue::getRecord
чтобы получитьList<Record>
- Извлеките два поля каждой записи, используя
Record::getFields
получитьList<Pair<RecordField, RecordField>>
- Извлечь значения из
RecordFields
сRecordFields::getValue
, даваяList<Pair<Value, Value>>
- Извлечь
Int64
, который является псевдонимом дляlong
, а такжеString
отValue
объекты, чтобы получить финалList<Pair<Long, String>>
Шаги 2. - 4. могут быть выполнены аккуратно, используя потоковый интерфейс Java. Показанный код предназначен для необработанных типов gRPC, начиная с 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());
}
}
Предполагая, что у вас есть следующий шаблон daml:
template ListOfTuples
with
party : Party
listOfTuples : [(Int, Text)]
where
signatory party
который был преобразован в com.daml.ledger.javaapi.data.Record
с Java API, вы можете преобразовать его в List<Pair<Long, String>>
рассматривая кортежи в списке также как Record
s:
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());
}