class Source extends StripeJsonModel implements StripePaymentSource {

    @NonNull
    @Override
    public JSONObject toJson() {
        JSONObject jsonObject = new JSONObject();
        try {
            putStringIfNotNull(jsonObject, FIELD_ID, mId);
            jsonObject.put(FIELD_OBJECT, VALUE_SOURCE);
            jsonObject.put(FIELD_AMOUNT, mAmount);
            putStringIfNotNull(jsonObject, FIELD_CLIENT_SECRET, mClientSecret);
            putStripeJsonModelIfNotNull(jsonObject, FIELD_CODE_VERIFICATION, mCodeVerification);
            jsonObject.put(FIELD_CREATED, mCreated);
            putStringIfNotNull(jsonObject, FIELD_CURRENCY, mCurrency);
            putStringIfNotNull(jsonObject, FIELD_FLOW, mFlow);
            jsonObject.put(FIELD_LIVEMODE, mLiveMode);

            JSONObject metaDataObject = StripeJsonUtils.mapToJsonObject(mMetaData);
            if (metaDataObject != null) {
                jsonObject.put(FIELD_METADATA, metaDataObject);
            }

            JSONObject sourceTypeJsonObject = mapToJsonObject(mSourceTypeData);

            if (sourceTypeJsonObject != null) {
                jsonObject.put(mTypeRaw, sourceTypeJsonObject);
            }

            putStripeJsonModelIfNotNull(jsonObject, FIELD_OWNER, mOwner);
            putStripeJsonModelIfNotNull(jsonObject, FIELD_RECEIVER, mReceiver);
            putStripeJsonModelIfNotNull(jsonObject, FIELD_REDIRECT, mRedirect);
            putStringIfNotNull(jsonObject, FIELD_STATUS, mStatus);
            putStringIfNotNull(jsonObject, FIELD_TYPE, mTypeRaw);
            putStringIfNotNull(jsonObject, FIELD_USAGE, mUsage);

        } catch (JSONException ignored) { }
        return jsonObject;
    }

      Source(
            String id,
            Long amount,
            String clientSecret,
            SourceCodeVerification codeVerification,
            Long created,
            String currency,
            @SourceFlow String flow,
            Boolean liveMode,
            Map<String, String> metaData,
            SourceOwner owner,
            SourceReceiver receiver,
            SourceRedirect redirect,
            @SourceStatus String status,
            Map<String, Object> sourceTypeData,
            StripeSourceTypeModel sourceTypeModel,
            @SourceType String type,
            String rawType,
            @Usage String usage
    );

}