Ah, I figured out that I can use the layered API to decode each item in the list individually:
kj::ArrayPtr<const char> text;
capnp::MallocMessageBuilder mb;
capnp::JsonCodec codec;
kj::ArrayBuilder<kj::Promise<void>> promises;
auto value = mb.initRoot<capnp::JsonValue>(); codec.decodeRaw(text, value);
for (auto&& entry: value.getArray()) {
auto request = cap.fooRequest();
codec.decode(entry, request);
promises.add(request.send().ignoreResult());
}
However, I'd still be curious to know how to create a request from an existing struct, if that's at all possible!