@Override
    public TStruct readStructBegin() throws TException {
        readCurrentContext();

        JsonNode structElem;
        // Reading a new top level struct if the only item on the stack
        // is the BaseContext
        if (1 == contextStack.size()) {
            try {
                readRoot();
            } catch (IOException e) {
                throw new TException("Could not parse input, is it valid json?", e);
            }
            if (root == null) {
                throw new TException("parser.next() has nothing to parse!");
            }
            structElem = root;
        } else {
            structElem = getCurrentContext().getCurrentChild();
        }

        if (getCurrentContext().isMapKey()) {
            try {
                structElem = OBJECT_MAPPER.readTree(structElem.asText());
            } catch (IOException e) {
                throw new TException("Could not parse map key, is it valid json?", e);
            }
        }

        if (!structElem.isObject()) {
            throw new TException("Expected Json Object!");
        }

        final Class<?> fieldClass = getCurrentFieldClassIfIs(TBase.class);
        if (fieldClass != null) {
            pushContext(new StructContext(structElem, fieldClass));
        } else {
            pushContext(new StructContext(structElem));
        }
        return ANONYMOUS_STRUCT;
    }
Write out the given value, either as a JSON name (meaning it's
escaped by quotes), or a value. The TypedParser knows how to
handle the writing.
thrift/thrift0.13/src/main/java/com/linecorp/armeria/common/thrift/text/TTextProtocol.java