简体   繁体   中英

how to unmarshall JSON Array to array of classes

I have JSON array I need to get in to either a List or Array of Classes. I tried, not much info on it, the Camel DataFormats UseList=true, but, I don't think I have a handle on what to expect from UseList on DataFormats.

<dataFormats>
            <!-- include="NOT_NULL" -->
            <json id="Json2Pojo" library="Jackson" prettyPrint="true" unmarshalTypeName="com.ga.dig.fleet.entities.TokenEntities"/>
            <json disableFeatures="FAIL_ON_UNKNOWN_PROPERTIES"
                id="AssetEntitiesPojo" library="Jackson"
                prettyPrint="true"
                unmarshalTypeName="com.ga.dig.fleet.entities.AssetEntities" useList="true"/>
            <json disableFeatures="FAIL_ON_UNKNOWN_PROPERTIES"
                id="TagEntitiesPojo" library="Jackson"
                prettyPrint="true"
                unmarshalTypeName="com.ga.dig.fleet.entities.TagEntities" useList="true"/>
        </dataFormats>

The inbound JSON looks like, show only one block - can be long

[
    {
        "tagDisplayMode": "Default",
        "maxHistoryQueueSize": 0,
        "pollCycleInMilliseconds": 600000,
        "doRecordObservationIfModeNotMet": true,
        "timeZoneId": "Eastern Standard Time",
        "isActive": true,
        "isProduction": false,
        "isLocked": false,
        "lockCreatedTime": null,
        "lockedByUserId": null,
        "lockedByUsername": null,
        "copiedFromAssetGuid": "da3909da-6296-463d-8c01-41694a51ac61",
        "connectionGuid": "c7d25ac9-9e71-4ba5-938b-71ccef762373",
        "customMaxHistoryQueueSize": false,
        "customPollCycleInterval": false,
        "blueprintGuid": "be1e2d8e-0b88-4a23-aa66-c6abe59b0d50",
        "source_TZ": 32,
        "source_DST": false,
        "asset_TZ": 32,
        "asset_DST": false,
        "displayName": "BC101_Compressor",
        "description": "",
        "note": "",
        "calculatedVariablesValid": false,
        "calculatedVariablesHasLatestData": false,
        "customTimeZone": true,
        "lineage": "Rendered in procs only",
        "connectionDisplayName": "BP Cooper River BC101",
        "assetBlueprintDisplayName": "CHM_CENTRIFUGAL_COMPRESSOR_5STG_S",
        "modes": null,
        "assetTags": null,
        "collectionType": "SampleAndHold",
        "blueprintVersion": "1.0.0",
        "deploymentNote": null,
        "parentGuid": "e0ad48b5-0c4c-4efc-ba42-53771c416aaa",
        "createdDate": "2019-05-07T21:32:05.1323509Z",
        "createdBy": "7a4cb4d4-8b54-4a8e-977e-f38d4c6f73bb",
        "itemGuid": "50480a32-cd65-4b93-94f8-4ba50cf6dec5",
        "isDeleted": false,
        "ordinalPosition": 19,
        "itemCategory": "InstanceEntity",
        "lastChangedDate": "2019-05-07T22:33:32.1101895Z",
        "lastChangedBy": "7a4cb4d4-8b54-4a8e-977e-f38d4c6f73bb",
        "links": [
            {
                "rel": "self",
                "href": "https://apm-sm-analytic-svc-prod.app-api.aws-usw02-pr.p.io/api/v1/assets/50480a32-cd65-4b93-94f8-4ba50cf6dec5"
            },
            {
                "rel": "blueprint",
                "href": "https://apm-sm-blueprint-svc-prod.app-api.aws-usw02-pr.p.io/api/v0/blueprints/be1e2d8e-0b88-4a23-aa66-c6abe59b0d50?version=1.0.0"
            },
            {
                "rel": "modeltagrules",
                "href": "https://apm-sm-blueprint-svc-prod.app-api.aws-usw02-pr.p.io/api/v0/blueprints/be1e2d8e-0b88-4a23-aa66-c6abe59b0d50/modeltagrules?version=1.0.0"
            },
            {
                "rel": "assettagrules",
                "href": "https://apm-sm-blueprint-svc-prod.app-api.aws-usw02-pr.p.io/api/v0/blueprints/be1e2d8e-0b88-4a23-aa66-c6abe59b0d50/assettagrules?version=1.0.0"
            },
            {
                "rel": "modes",
                "href": "https://apm-sm-analytic-svc-prod.app-api.aws-usw02-pr.p.io/api/v1/assets/50480a32-cd65-4b93-94f8-4ba50cf6dec5/modes"
            },
            {
                "rel": "tags",
                "href": "https://apm-sm-analytic-svc-prod.app-api.aws-usw02-pr.p.io/api/v1/assets/50480a32-cd65-4b93-94f8-4ba50cf6dec5/tags"
            },
            {
                "rel": "trainingdata",
                "href": "https://apm-sm-analytic-svc-prod.app-api.aws-usw02-pr.p.io/api/v1/assets/50480a32-cd65-4b93-94f8-4ba50cf6dec5/trainingdata"
            },
            {
                "rel": "historicdatablobkey",
                "href": "https://apm-sm-analytic-svc-prod.app-api.aws-usw02-pr.p.io/api/v1/assets/50480a32-cd65-4b93-94f8-4ba50cf6dec5/historicdatablobkey"
            }
        ]
    },
    {

... on and on... fortunately I am only concerned with a few of these elements. isActive, displayName, and itemGuid

My JSON mapper class

import java.util.HashMap;
import java.util.Map;

//JSON READ ANNOTATIONS affect how Jackson parses JSON into POJO's
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.JsonIgnore;

//@JsonIgnoreProperties({ "token_type", "scope", "jti" })
public class AssetEntities {

    private static final long serialVersionUID = 201903211122L;

    @JsonProperty("isActive")
    private String isActive;
    @JsonProperty("displayName")
    private String displayName;
    @JsonProperty("itemGuid")
    private String itemGuid;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    public String getIsActive() {
        return isActive;
    }   
    public String getDisplayName() {
        return displayName;
    }   
    public String getItemGuid() {
        return itemGuid;
    }
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonSetter("isActive")
    public void setIsActive(String isActive) {
         this.isActive = isActive;
    }
    @JsonSetter("displayName")
    public void setDisplayName(String displayName) {
         this.displayName = displayName;
    }
    @JsonSetter("itemGuid")
    public void setItemGuid(String itemGuid) {
         this.itemGuid = itemGuid;
    }
    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

    @Override
    public String toString() {
        return  "[ isActive=" + isActive + ", displayName=" + displayName + ", itemGuid=" + itemGuid + " ]";
    }   
}

Now, this is working as far as mapping the JSON, but, I get ( as expected - the toString() method in the mapping class) a long string of the requested values.

BodyType:String, Body:[ isActive=true, displayName=BC101_Compressor, itemGuid=50480a32-cd65-4b93-94f8-4ba50cf6dec5 ][ isActive=true, displayName=BC102_Compressor, itemGuid=49380230-99eb-4fee-a9a3-e187e4c658ee ][ isActive=true, displayName=BC104_Expander, itemGuid=05d52eb9-6d45-4683-bff2-e079d1d2f745 ][ isActive=true, displayName=BC105_Steam_Turbine, itemGuid=1ddeae49-07ab-4872-817d-ba1dc1528fa2 ][ isActive=true, displayName=BC901_Steam_Turbine, itemGuid=b4acecbb-fac1-4a99-ab95-24e1bc7f4286 ][ isActive=true, displayName=BCG101_Gearbox, itemGuid=49366bcc-bb6a-426f-8c5c-6d65d675ac90 ][ isActive=true, displayName=BCG102_Gearbox, itemGuid=f4402fb9-a638-46e1-93d3-bcb927c44ee4 ][ isActive=true, displayName=BCG901_Gearbox, itemGuid=cd46fc06-dc08-42c7-a73e-839d3b27d683 ][ isActive=true, displayName=BCM101_Motor, itemGuid=6cf41883-36c1-4eca-8325-54588982bdc8 ][ isActive=true, displayName=BCM102_Motor, itemGuid=652e4041-3c2b-410a-8ba0-12a2a53ec730 ][ isActive=true, displayName=BCM901_Generator, itemGuid=96de09f5-6dac-... [Body clipped after 1000 chars, total length is 1677]

I know it is my implementation or mapping, I cannot figure out at this time how to get an Array of Classes from the JSON unmarshalling. thank you for your help!

THIS IS the Blueprint/Spring XML

        <!-- GET Asset and Asset tag List for Customer Project Implementation -->
        <route autoStartup="true" id="get.impl.assets">
            <!--  every 5 minutes -->
            <from id="get.assets" uri="timer://getassets?fixedRate=true&amp;period=150000"/>
            <process id="a1" ref="assetEntitesProcessor"/>
            <choice id="c1">
                <when id="w1">
                    <ognl>request.headers.PDXDB == true</ognl>
                    <process id="a2" ref="assetTokenProcessor"/>
                    <choice id="c2">
                        <when id="w2">
                            <ognl>request.headers.TKNDB == true</ognl>
                            <process id="a3" ref="assetUploadProcessor"/>
                            <setHeader headerName="CamelHttpUri" id="h1">
                                <simple>${header.UPLOADURL}</simple> <!-- <simple>${header.UPLOADURL}?throwExceptionOnFailure=false</simple> -->
                            </setHeader>
                            <setHeader headerName="CamelHttpMethod" id="h2">
                                <constant>GET</constant>
                            </setHeader>
                            <to id="get1" uri="http4://apm-timeseries-query-svc-prod.app-api.aws-usw02-pr.predix.io:443/v2/time_series/upload?throwExceptionOnFailure=false"/>
                            <unmarshal id="JsonAssets" ref="AssetEntitiesPojo"/>
                            <process id="p1" ref="getAssets"/>
<!-- TODO extract elements of AssetEntities  
                            <split id="as1" strategyRef="tsAggregationStrategy" streaming="true">
                                <simple>${body}</simple>
                                <log id="al6" loggingLevel="INFO" message="Split line ${body}"/>
                                <process id="p1" ref="getAssets"/>
                            </split>
-->                         
                            <log id="l1" loggingLevel="INFO" message="HTTP4 Upload Response: ${body}"/>
                            <convertBodyTo id="c1" type="java.lang.String"/>
                            <to id="t1" uri="{{afteruploadLocation}}"/>
                        </when>
                    </choice>
                </when>
            </choice>
        </route>

尝试:

List<AssetEntities> list = new ObjectMapper().readValue(input, new TypeReference<List<AssetEntities>> {})

Thank you Fracdroid, yes, your answer works perfectly. I was under the impression that the DataFormats useList would somehow do this. so here is the result. I broke expression up to resolve dependencies.

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.core.type.TypeReference;

public class JsonMapperAssets implements Processor {

    private static Logger log = LoggerFactory.getLogger(JsonMapperAssets.class.getName());

    @Override
    public void process(Exchange exchange) throws JsonParseException, JsonMappingException, IOException {

        log.info("JSON Mapper of Assets :: Start");

        ObjectMapper mapper = new ObjectMapper();
        ObjectReader reader = mapper.reader().forType(new TypeReference<List<AssetEntities>>(){});
        List<AssetEntities> jsonAsssetsList = reader.readValue(exchange.getIn().getBody(String.class));

        exchange.getIn().setBody(jsonAsssetsList);

        log.info("JSON Mapper of Assets :: finish");

   }

Now I can use the Camel Splitter EIP

<route autoStartup="true" id="get.impl.assets">
    <from id="get.assets" uri="timer://getassets?fixedRate=true&amp;period=150000"/>
    <process id="a1" ref="assetEntitesProcessor"/>
    <choice id="c1">
        <when id="w1">
            <ognl>request.headers.PDXDB == true</ognl>
            <process id="a2" ref="assetTokenProcessor"/>
            <choice id="c2">
                <when id="w2">
                    <ognl>request.headers.TKNDB == true</ognl>
                    <process id="a3" ref="assetUploadProcessor"/>
                    <setHeader headerName="CamelHttpUri" id="h1">
                        <simple>${header.UPLOADURL}</simple>
                    </setHeader>
                    <setHeader headerName="CamelHttpMethod" id="h2">
                        <constant>GET</constant>
                    </setHeader>
                    <to id="get1" uri="http4://apm-timeseries-query-svc-prod.app-api.aws-usw02-pr.predix.io:443/v2/time_series/upload?throwExceptionOnFailure=false"/>
                    <log id="l1" loggingLevel="INFO" message="JSON Response: ${body}"/>
                    <convertBodyTo id="c1" type="java.lang.String"/>
                    <process id="jsonmapperassets" ref="jsonMapperAssets" />
                    <split id="as1" strategyRef="tsAggregationStrategy" streaming="true">
                        <simple>${body}</simple>
                        <log id="al6" loggingLevel="INFO" message="Split line ${body}"/>
                        <process id="p1" ref="getAssets"/>
                    </split>

                    <log id="l2" loggingLevel="INFO" message="HTTP4 Upload Response: ${body}"/>

                    <to id="t1" uri="{{afteruploadLocation}}"/>
                </when>
            </choice>
        </when>
    </choice>
</route>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM