I am trying create an object of the given class but am not able to cover the Arc.container().instance() lines. Could you please check what I am missing here. The code is given below;
/**
* Track Tag handler
*/
#Slf4j
#ApplicationScoped
#Unremovable
#SuppressWarnings({
"checkstyle:BooleanExpressionComplexity",
"PMD.ExcessiveClassLength",
"PMD.ExcessiveImports",
"PMD.GodClass",
"PMD.TooManyMethods"
})
public class TrackTagHandler implements TrackTagEventHandler
{
/**
* Tag service to handle business logic
*/
private final TagBusinessService tagBusinessService;
/**
* Number pool for generating new tag id
*/
private final NumberPoolService numberPoolService;
/**
* Topology data service for retrieving device entities
*/
private final TopologyLookupService topologyLookupService;
/**
* Device management gram service for creating device state request gram
*/
private final DeviceManagementService deviceManagementService;
/**
* Track handler for returning the track-tag form
*/
#SuppressWarnings("checkstyle:VisibilityModifier")
TrackTagTrackProvider trackTagTrackProvider;
/**
* Switch handler for returning the track-tag form
*/
#SuppressWarnings("checkstyle:VisibilityModifier")
TrackTagSwitchProvider trackTagSwitchProvider;
/**
* Roadway Worker & Blue Signal handler for returning the track-tag form
*/
#SuppressWarnings("checkstyle:VisibilityModifier")
TrackTagRoadwayBlueSignalProvider trackTagRoadwayBlueSignalProvider;
/**
* On Station handler for returning the track-tag form
*/
#SuppressWarnings("checkstyle:VisibilityModifier")
TrackTagOSProvider trackTagOSProvider;
/**
* Signal handler for returning the track-tag form
*/
#SuppressWarnings("checkstyle:VisibilityModifier")
TrackTagSignalProvider trackTagSignalProvider;
/**
* Misc. Device handler for returning the track-tag form
*/
#SuppressWarnings("checkstyle:VisibilityModifier")
TrackTagMiscDeviceProvider trackTagMiscDeviceProvider;
/**
* TrackTagHandler constructor<br>
* Use constructor injection to get the required services
*
* #param trackTagTrackProvider Track handler for returning the track-tag form
* #param trackTagSwitchProvider Switch handler for returning the track-tag form
* #param trackTagRoadwayBlueSignalProvider Roadway Worker & Blue Signal handler for returning the track-tag form
* #param trackTagOSProvider On Station handler for returning the track-tag form
* #param trackTagSignalProvider Signal handler for returning the track-tag form
* #param trackTagMiscDeviceProvider Misc. Device handler for returning the track-tag form
*/
#Inject
public TrackTagHandler(
final TrackTagTrackProvider trackTagTrackProvider,
final TrackTagSwitchProvider trackTagSwitchProvider,
final TrackTagRoadwayBlueSignalProvider trackTagRoadwayBlueSignalProvider,
final TrackTagOSProvider trackTagOSProvider,
final TrackTagSignalProvider trackTagSignalProvider,
final TrackTagMiscDeviceProvider trackTagMiscDeviceProvider)
{
this.trackTagTrackProvider = trackTagTrackProvider;
this.trackTagSwitchProvider = trackTagSwitchProvider;
this.trackTagRoadwayBlueSignalProvider = trackTagRoadwayBlueSignalProvider;
this.trackTagOSProvider = trackTagOSProvider;
this.trackTagSignalProvider = trackTagSignalProvider;
this.trackTagMiscDeviceProvider = trackTagMiscDeviceProvider;
this.tagBusinessService = Arc.container().instance(TagBusinessService.class).get();
this.numberPoolService = Arc.container().instance(NumberPoolService.class).get();
this.topologyLookupService = Arc.container().instance(TopologyLookupService.class).get();
this.deviceManagementService = Arc.container().instance(DeviceManagementService.class).get();
}
/**
* Handle event requesting
*/
#Override
#SuppressWarnings({
"PMD.ExcessiveMethodLength", "PMD.CyclomaticComplexity"
})
public TagEventContext handleEvent(final TagEventContext event)
{
event.setRequestInfo(event.getEvent().getBinding());
final RequestInfo requestInfo = event.getRequestInfo();
if (Optional.ofNullable(requestInfo).isEmpty())
{
throw new BadRequestException(MessageConstants.INVALID_REQUEST);
}
log.info("Calling track tag event handler for {}", event.getEvent());
switch (event.getEvent())
{
case Read:
final TagInfo tagInfo = getActiveTag(requestInfo.getTagId());
event.setTrackTag(setToTrackTag(tagInfo, event));
break;
case Pending:
// Set initials
final String dispatcherInitials =
event.getProperties().get(InitializeProperty.rtcInitials.getBinding()).toString();
final PendingRequestInfo pendingRequestInfo = PendingRequestInfo.builder()
.deviceIds(requestInfo.getDeviceIds())
.logicalPosition(requestInfo.getLogicalPosition())
.userId(requestInfo.getUserId())
.deviceType(requestInfo.getDeviceType())
.tagType(requestInfo.getTagType())
.build();
event.setTrackTag(createPendingTag(pendingRequestInfo, dispatcherInitials, event));
break;
case Update:
final UpdateRequestInfo updateRequestInfo = UpdateRequestInfo.builder()
.comments(requestInfo.getComments())
.estimatedRemovalTime(requestInfo.getEstimatedRemovalTime())
.logicalPosition(requestInfo.getLogicalPosition())
.name(requestInfo.getName())
.pseudo(requestInfo.isPseudo())
.tagId(requestInfo.getTagId())
.timeZone(requestInfo.getTimeZone())
.userId(requestInfo.getUserId())
.build();
final TagData tagData = getTagData(requestInfo.getTagId());
if (tagData.getCurrentTagInfo().getStatus() == TagStatus.PENDING)
{
createActiveTag(updateRequestInfo, event);
}
else
{
updateTag(updateRequestInfo, event);
}
break;
case Remove:
final DeleteRequestInfo deleteRequestInfo = DeleteRequestInfo.builder()
.comments(requestInfo.getComments())
.logicalPosition(requestInfo.getLogicalPosition())
.tagId(requestInfo.getTagId())
.userId(requestInfo.getUserId())
.build();
deleteTag(deleteRequestInfo, event);
break;
case RemovalComments:
final UpdateDeleteRequestInfo updateDeleteRequestInfo = UpdateDeleteRequestInfo.builder()
.action(requestInfo.getAction())
.removalComments(requestInfo.getRemovalComments())
.tagId(requestInfo.getTagId())
.build();
updateRemovalCommentsToDeleteTag(updateDeleteRequestInfo, event);
break;
case Reset:
final TagInfo resetTagInfo = resetTag(requestInfo.getTagId(), event);
event.setTrackTag(setToTrackTag(resetTagInfo, event));
break;
case Cancel:
cancelTag(requestInfo.getTagId(), event);
break;
case DeviceRecord:
final DeviceUpdateRequestInfo deviceUpdateRequestInfo = DeviceUpdateRequestInfo.builder()
.deviceAction(requestInfo.getDeviceAction())
.logicalPosition(requestInfo.getLogicalPosition())
.recordId(requestInfo.getRecordId())
.userId(requestInfo.getUserId())
.build();
updateDeviceRecord(deviceUpdateRequestInfo);
break;
case TagTypeChange:
final TagTypeUpdateRequestInfo tagTypeUpdateRequestInfo = TagTypeUpdateRequestInfo.builder()
.logicalPosition(requestInfo.getLogicalPosition())
.tagId(requestInfo.getTagId())
.deviceType(requestInfo.getDeviceType())
.tagType(requestInfo.getTagType())
.userId(requestInfo.getUserId())
.build();
final TagInfo modifiedTagInfo = updateTagType(tagTypeUpdateRequestInfo);
event.setTrackTag(setToTrackTag(modifiedTagInfo, event));
break;
default:
}
return event;
}
}
TrackTagEvent
/**
* Track Tag form events with handlers
*/
public enum TrackTagEvent implements DynamicFormEvent<TagEventContext>
{
/** **/
Read
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
Pending
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
Update
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
Remove
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
RemovalComments
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
Reset
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
Cancel
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
DeviceRecord
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
},
/** **/
TagTypeChange
{
#Override
public TagEventContext handleEvent(final TagEventContext event)
{
return Arc.container().instance(TrackTagHandler.class).get().handleEvent(event);
}
};
/** The binding value */
#Getter
private final String binding;
/** Constructor to set binding to property name */
TrackTagEvent()
{
this.binding = name();
}
/** Constructor to set binding to given value */
TrackTagEvent(final String binding)
{
this.binding = binding;
}
}
TagEventContext
/**
* Track Tag Event
*/
#Slf4j
#Data
#NoArgsConstructor
public class TagEventContext implements TrackTagEventContext<TrackTag>
{
/**
* Serializable
*/
private static final long serialVersionUID = 1L;
/**
* Id
*/
private long id;
/**
* Form id
*/
private String formId;
/**
* Form version
*/
private String version;
/**
* Event
*/
private TrackTagEvent event;
/**
* Control list
*/
private List<ControlListItem> controlList;
/**
* Properties
*/
private Map<String, Object> properties;
/**
* Dynamic Form update
*/
private DynamicForm dynamicForm;
/**
* Feedback
*/
private Feedback feedback;
/**
* The Track Tag Information
*/
#JsonIgnore
private TrackTag trackTag;
/**
* Request Information
*/
#JsonIgnore
private RequestInfo requestInfo;
/**
* The publish type
*/
#JsonIgnore
private PublishType publishType = PublishType.NO_PUBLISH;
/**
* Set dynamic form and copy required fields to context
*/
#Override
public void setDynamicForm(final DynamicForm form)
{
this.dynamicForm = form;
if (form != null && form.getMetadata() != null)
{
this.formId = form.getMetadata().getFormId();
this.version = Integer.toString(form.getVersion());
}
}
/**
* Update control list
*/
#Override
public List<ControlListItem> updateControlListFromTrackTag()
{
if (trackTag == null)
{
log.debug("No tag specified");
return controlList;
}
id = trackTag.getTagId();
updateControlListWithDefaultValues();
return controlList;
}
/**
* Get RequestInfo object from properties based on request
*/
private RequestInfo fetchRequestInfo(final String request)
{
final ObjectMapper mapper = new ObjectMapper();
try
{
mapper.registerModule(new JavaTimeModule());
final String jsonValue = mapper.writeValueAsString(( properties.get(request) ));
return mapper.readValue(jsonValue, RequestInfo.class);
}
catch (final JsonProcessingException ex)
{
log.error(ex.getMessage());
return null;
}
}
/**
* Set RequestInfo object to context
*/
public void setRequestInfo(final String request)
{
final RequestInfo info = fetchRequestInfo(request);
this.requestInfo = info;
}
}
After covering the costructor, I am supposed to cover the handleEvent() method. But am stuck at the initial place only.
I tried writing few testcases, but unable to understand how to cover that Arc.container().instance(). Below is what I have tried so far;
class TrackTagHandlerTest
{
final ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
#Inject TrackTagHandler trackTagHandler;
#Inject TrackTagProvider trackTagProvider;
#Inject TrackTagSwitchProvider trackTagSwitchProvider;
#Inject TrackTagRoadwayBlueSignalProvider trackTagRoadwayBlueSignalProvider;
#Inject TrackTagOSProvider trackTagOSProvider;
#Inject TrackTagSignalProvider trackTagSignalProvider;
#Inject TrackTagMiscDeviceProvider trackTagMiscDeviceProvider;
#Inject TagBusinessService tagBusinessService;
#Test
void testTrackTagHandleEvent() throws IOException
{
InputData request = mapper
.readValue(Thread.currentThread().getContextClassLoader().getResource("request.json"), InputData.class);
TrackTagTrackProvider trackTagProvider = new TrackTagTrackProvider();
TagEventContext context = trackTagProvider.createEvent(TrackTagEvent.Read, request);
context.setDynamicForm(new DynamicForm());
context.setFeedback(new Feedback());
assertNotNull(context.getProperties());
TrackTagHandler th = new TrackTagHandler(trackTagProvider, trackTagSwitchProvider, trackTagRoadwayBlueSignalProvider, trackTagOSProvider, trackTagSignalProvider, trackTagMiscDeviceProvider);
TagEventContext returnContext = TrackTagEvent.Read.handleEvent(context);
}
}
Related
I have written below code to read avro schema records from Kafka topic. I have taken .avsc and generate a class(paymentengine) using maven and reading record with SpecificAvroRecord. I am able to read these records successfully. Now, I need to do some validation on these records and insert these records into a table.
package com.example.consumer;
import io.confluent.kafka.serializers.KafkaAvroDeserializer;
import io.confluent.kafka.serializers.KafkaAvroDeserializerConfig;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class PayKafkaSpecifcAvro {
public static void main(String[] args) {
// setting properties
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, KafkaAvroDeserializer.class.getName());
props.put(ConsumerConfig.GROUP_ID_CONFIG, "group1");
props.put(KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG, "true");
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
props.put(KafkaAvroDeserializerConfig.SCHEMA_REGISTRY_URL_CONFIG, "http://localhost:8081");
//name topic
String topic = "pengine";
// create the consumer
KafkaConsumer<String, pengine> consumer = new KafkaConsumer<String, pengine>(props);
//subscribe to topic
consumer.subscribe(Collections.singleton(topic));
System.out.println("Waiting for the data...");
while (true) {
ConsumerRecords<String, pengine> records = consumer.poll(Duration.ofMillis(5000));
for (ConsumerRecord<String, pengine> record : records) {
System.out.println(record.value());
System.out.println((record.value().getVcp()));
consumer.commitSync();
}
}
}
}
Output :
As the output is in JSON format, how can I convert it into a String and Compare it? I need to compare ACH and VCP value and if the values are same then have to flag that row as error. Also, converting these records in string would help me to insert these records into database as well.
pengine class:
package com.example.consumer; /**
* Autogenerated by Avro
*
* DO NOT EDIT DIRECTLY
*/
import org.apache.avro.message.BinaryMessageDecoder;
import org.apache.avro.message.BinaryMessageEncoder;
import org.apache.avro.message.SchemaStore;
import org.apache.avro.specific.SpecificData;
import org.apache.avro.util.Utf8;
#org.apache.avro.specific.AvroGenerated
public class pengine extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = -3169039590588895557L;
public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"pengine\",\"fields\":[{\"name\":\"tin\",\"type\":\"string\"},{\"name\":\"ach\",\"type\":\"string\"},{\"name\":\"vcp\",\"type\":\"string\"}]}");
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
private static SpecificData MODEL$ = new SpecificData();
private static final BinaryMessageEncoder<pengine> ENCODER =
new BinaryMessageEncoder<pengine>(MODEL$, SCHEMA$);
private static final BinaryMessageDecoder<pengine> DECODER =
new BinaryMessageDecoder<pengine>(MODEL$, SCHEMA$);
/**
* Return the BinaryMessageEncoder instance used by this class.
* #return the message encoder used by this class
*/
public static BinaryMessageEncoder<pengine> getEncoder() {
return ENCODER;
}
/**
* Return the BinaryMessageDecoder instance used by this class.
* #return the message decoder used by this class
*/
public static BinaryMessageDecoder<pengine> getDecoder() {
return DECODER;
}
/**
* Create a new BinaryMessageDecoder instance for this class that uses the specified {#link SchemaStore}.
* #param resolver a {#link SchemaStore} used to find schemas by fingerprint
* #return a BinaryMessageDecoder instance for this class backed by the given SchemaStore
*/
public static BinaryMessageDecoder<pengine> createDecoder(SchemaStore resolver) {
return new BinaryMessageDecoder<pengine>(MODEL$, SCHEMA$, resolver);
}
/**
* Serializes this pengine to a ByteBuffer.
* #return a buffer holding the serialized data for this instance
* #throws java.io.IOException if this instance could not be serialized
*/
public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException {
return ENCODER.encode(this);
}
/**
* Deserializes a pengine from a ByteBuffer.
* #param b a byte buffer holding serialized data for an instance of this class
* #return a pengine instance decoded from the given buffer
* #throws java.io.IOException if the given bytes could not be deserialized into an instance of this class
*/
public static pengine fromByteBuffer(
java.nio.ByteBuffer b) throws java.io.IOException {
return DECODER.decode(b);
}
private CharSequence tin;
private CharSequence ach;
private CharSequence vcp;
/**
* Default constructor. Note that this does not initialize fields
* to their default values from the schema. If that is desired then
* one should use <code>newBuilder()</code>.
*/
public pengine() {}
/**
* All-args constructor.
* #param tin The new value for tin
* #param ach The new value for ach
* #param vcp The new value for vcp
*/
public pengine(CharSequence tin, CharSequence ach, CharSequence vcp) {
this.tin = tin;
this.ach = ach;
this.vcp = vcp;
}
public SpecificData getSpecificData() { return MODEL$; }
public org.apache.avro.Schema getSchema() { return SCHEMA$; }
// Used by DatumWriter. Applications should not call.
public Object get(int field$) {
switch (field$) {
case 0: return tin;
case 1: return ach;
case 2: return vcp;
default: throw new org.apache.avro.AvroRuntimeException("Bad index");
}
}
// Used by DatumReader. Applications should not call.
#SuppressWarnings(value="unchecked")
public void put(int field$, Object value$) {
switch (field$) {
case 0: tin = (CharSequence)value$; break;
case 1: ach = (CharSequence)value$; break;
case 2: vcp = (CharSequence)value$; break;
default: throw new org.apache.avro.AvroRuntimeException("Bad index");
}
}
/**
* Gets the value of the 'tin' field.
* #return The value of the 'tin' field.
*/
public CharSequence getTin() {
return tin;
}
/**
* Sets the value of the 'tin' field.
* #param value the value to set.
*/
public void setTin(CharSequence value) {
this.tin = value;
}
/**
* Gets the value of the 'ach' field.
* #return The value of the 'ach' field.
*/
public CharSequence getAch() {
return ach;
}
/**
* Sets the value of the 'ach' field.
* #param value the value to set.
*/
public void setAch(CharSequence value) {
this.ach = value;
}
/**
* Gets the value of the 'vcp' field.
* #return The value of the 'vcp' field.
*/
public CharSequence getVcp() {
return vcp;
}
/**
* Sets the value of the 'vcp' field.
* #param value the value to set.
*/
public void setVcp(CharSequence value) {
this.vcp = value;
}
/**
* Creates a new pengine RecordBuilder.
* #return A new pengine RecordBuilder
*/
public static pengine.Builder newBuilder() {
return new pengine.Builder();
}
/**
* Creates a new pengine RecordBuilder by copying an existing Builder.
* #param other The existing builder to copy.
* #return A new pengine RecordBuilder
*/
public static pengine.Builder newBuilder(pengine.Builder other) {
if (other == null) {
return new pengine.Builder();
} else {
return new pengine.Builder(other);
}
}
/**
* Creates a new pengine RecordBuilder by copying an existing pengine instance.
* #param other The existing instance to copy.
* #return A new pengine RecordBuilder
*/
public static pengine.Builder newBuilder(pengine other) {
if (other == null) {
return new pengine.Builder();
} else {
return new pengine.Builder(other);
}
}
/**
* RecordBuilder for pengine instances.
*/
#org.apache.avro.specific.AvroGenerated
public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<pengine>
implements org.apache.avro.data.RecordBuilder<pengine> {
private CharSequence tin;
private CharSequence ach;
private CharSequence vcp;
/** Creates a new Builder */
private Builder() {
super(SCHEMA$);
}
/**
* Creates a Builder by copying an existing Builder.
* #param other The existing Builder to copy.
*/
private Builder(pengine.Builder other) {
super(other);
if (isValidValue(fields()[0], other.tin)) {
this.tin = data().deepCopy(fields()[0].schema(), other.tin);
fieldSetFlags()[0] = other.fieldSetFlags()[0];
}
if (isValidValue(fields()[1], other.ach)) {
this.ach = data().deepCopy(fields()[1].schema(), other.ach);
fieldSetFlags()[1] = other.fieldSetFlags()[1];
}
if (isValidValue(fields()[2], other.vcp)) {
this.vcp = data().deepCopy(fields()[2].schema(), other.vcp);
fieldSetFlags()[2] = other.fieldSetFlags()[2];
}
}
/**
* Creates a Builder by copying an existing pengine instance
* #param other The existing instance to copy.
*/
private Builder(pengine other) {
super(SCHEMA$);
if (isValidValue(fields()[0], other.tin)) {
this.tin = data().deepCopy(fields()[0].schema(), other.tin);
fieldSetFlags()[0] = true;
}
if (isValidValue(fields()[1], other.ach)) {
this.ach = data().deepCopy(fields()[1].schema(), other.ach);
fieldSetFlags()[1] = true;
}
if (isValidValue(fields()[2], other.vcp)) {
this.vcp = data().deepCopy(fields()[2].schema(), other.vcp);
fieldSetFlags()[2] = true;
}
}
/**
* Gets the value of the 'tin' field.
* #return The value.
*/
public CharSequence getTin() {
return tin;
}
/**
* Sets the value of the 'tin' field.
* #param value The value of 'tin'.
* #return This builder.
*/
public pengine.Builder setTin(CharSequence value) {
validate(fields()[0], value);
this.tin = value;
fieldSetFlags()[0] = true;
return this;
}
/**
* Checks whether the 'tin' field has been set.
* #return True if the 'tin' field has been set, false otherwise.
*/
public boolean hasTin() {
return fieldSetFlags()[0];
}
/**
* Clears the value of the 'tin' field.
* #return This builder.
*/
public pengine.Builder clearTin() {
tin = null;
fieldSetFlags()[0] = false;
return this;
}
/**
* Gets the value of the 'ach' field.
* #return The value.
*/
public CharSequence getAch() {
return ach;
}
/**
* Sets the value of the 'ach' field.
* #param value The value of 'ach'.
* #return This builder.
*/
public pengine.Builder setAch(CharSequence value) {
validate(fields()[1], value);
this.ach = value;
fieldSetFlags()[1] = true;
return this;
}
/**
* Checks whether the 'ach' field has been set.
* #return True if the 'ach' field has been set, false otherwise.
*/
public boolean hasAch() {
return fieldSetFlags()[1];
}
/**
* Clears the value of the 'ach' field.
* #return This builder.
*/
public pengine.Builder clearAch() {
ach = null;
fieldSetFlags()[1] = false;
return this;
}
/**
* Gets the value of the 'vcp' field.
* #return The value.
*/
public CharSequence getVcp() {
return vcp;
}
/**
* Sets the value of the 'vcp' field.
* #param value The value of 'vcp'.
* #return This builder.
*/
public pengine.Builder setVcp(CharSequence value) {
validate(fields()[2], value);
this.vcp = value;
fieldSetFlags()[2] = true;
return this;
}
/**
* Checks whether the 'vcp' field has been set.
* #return True if the 'vcp' field has been set, false otherwise.
*/
public boolean hasVcp() {
return fieldSetFlags()[2];
}
/**
* Clears the value of the 'vcp' field.
* #return This builder.
*/
public pengine.Builder clearVcp() {
vcp = null;
fieldSetFlags()[2] = false;
return this;
}
#Override
#SuppressWarnings("unchecked")
public pengine build() {
try {
pengine record = new pengine();
record.tin = fieldSetFlags()[0] ? this.tin : (CharSequence) defaultValue(fields()[0]);
record.ach = fieldSetFlags()[1] ? this.ach : (CharSequence) defaultValue(fields()[1]);
record.vcp = fieldSetFlags()[2] ? this.vcp : (CharSequence) defaultValue(fields()[2]);
return record;
} catch (org.apache.avro.AvroMissingFieldException e) {
throw e;
} catch (Exception e) {
throw new org.apache.avro.AvroRuntimeException(e);
}
}
}
#SuppressWarnings("unchecked")
private static final org.apache.avro.io.DatumWriter<pengine>
WRITER$ = (org.apache.avro.io.DatumWriter<pengine>)MODEL$.createDatumWriter(SCHEMA$);
#Override public void writeExternal(java.io.ObjectOutput out)
throws java.io.IOException {
WRITER$.write(this, SpecificData.getEncoder(out));
}
#SuppressWarnings("unchecked")
private static final org.apache.avro.io.DatumReader<pengine>
READER$ = (org.apache.avro.io.DatumReader<pengine>)MODEL$.createDatumReader(SCHEMA$);
#Override public void readExternal(java.io.ObjectInput in)
throws java.io.IOException {
READER$.read(this, SpecificData.getDecoder(in));
}
#Override protected boolean hasCustomCoders() { return true; }
#Override public void customEncode(org.apache.avro.io.Encoder out)
throws java.io.IOException
{
out.writeString(this.tin);
out.writeString(this.ach);
out.writeString(this.vcp);
}
#Override public void customDecode(org.apache.avro.io.ResolvingDecoder in)
throws java.io.IOException
{
org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff();
if (fieldOrder == null) {
this.tin = in.readString(this.tin instanceof Utf8 ? (Utf8)this.tin : null);
this.ach = in.readString(this.ach instanceof Utf8 ? (Utf8)this.ach : null);
this.vcp = in.readString(this.vcp instanceof Utf8 ? (Utf8)this.vcp : null);
} else {
for (int i = 0; i < 3; i++) {
switch (fieldOrder[i].pos()) {
case 0:
this.tin = in.readString(this.tin instanceof Utf8 ? (Utf8)this.tin : null);
break;
case 1:
this.ach = in.readString(this.ach instanceof Utf8 ? (Utf8)this.ach : null);
break;
case 2:
this.vcp = in.readString(this.vcp instanceof Utf8 ? (Utf8)this.vcp : null);
break;
default:
throw new java.io.IOException("Corrupt ResolvingDecoder.");
}
}
}
}
}
The record.value() is a PaymentEngine object, so you can use record.value().getAch() to get the value of arc. The vcp is same. So you can compare to them with the requiered value. You get the json on print because print is automatically call the object's toString() method.
I have a Request Class that contains another class object. Now I want to parse a nested JSON as Request Class Object.
I am trying using ObjectMapper but its throwing exceptions. Please help me to do that using java Jackson.
{
"filters":[
{
"key":"CustomerId",
"op":"=",
"value" : "1"
},
{
"key":"userName",
"op":"=",
"value" : "admin"
}
],
"startIndex" : 1,
"size" : 10,
"OrderBy" :
{
"propertyId" : "userName",
"Desc" : false
},
"TimeRange" : {
"startTimestamp" : 1,
"endTimestamp" :10
}
}
Logic:
public static class OrderBy {
private String propertyId;
private boolean desc = true;
}
class TimeRange {
private Long startTimestamp;
private Long endTimestamp;
}
class Filter {
private String propertyId;
private String op;
private Object value;
}
public class Request {
private List<Filter> filters;
private TimeRange timeRange;
private OrderBy orderBy;
private int startIndex = 0;
private int size = 20;
}
I give you a Jaskson Util Tools class.
package com.jackson.utils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* The class JacksonUtil
*
* json字符与对像转换
*
* #version: $Revision$ $Date$ $LastChangedBy$
*
*/
public final class JacksonUtil {
public static ObjectMapper objectMapper;
/**
* 使用泛型方法,把json字符串转换为相应的JavaBean对象。
* (1)转换为普通JavaBean:readValue(json,Student.class)
* (2)转换为List,如List<Student>,将第二个参数传递为Student
* [].class.然后使用Arrays.asList();方法把得到的数组转换为特定类型的List
*
* #param jsonStr
* #param valueType
* #return
*/
public static <T> T readValue(String jsonStr, Class<T> valueType) {
if (objectMapper == null) {
objectMapper = new ObjectMapper();
}
try {
return objectMapper.readValue(jsonStr, valueType);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* json数组转List
* #param jsonStr
* #param valueTypeRef
* #return
*/
public static <T> T readValue(String jsonStr, TypeReference<T> valueTypeRef){
if (objectMapper == null) {
objectMapper = new ObjectMapper();
}
try {
return objectMapper.readValue(jsonStr, valueTypeRef);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 把JavaBean转换为json字符串
*
* #param object
* #return
*/
public static String toJSon(Object object) {
if (objectMapper == null) {
objectMapper = new ObjectMapper();
}
try {
return objectMapper.writeValueAsString(object);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Now ,you can use blow code covert to Request :
String userBeanToJson = "your json string";//please replace this for your need json
Request jsonToUserBean = JacksonUtil.readValue(userBeanToJson, Request.class);
Hope it is useful for you.
This question already has answers here:
Retrofit Expected BEGIN_OBJECT but was BEGIN_ARRAY
(7 answers)
Closed 6 years ago.
Learning how to use Retrofit in my Android App, getting following error:
Please help if you can. Thank you,
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
here is my code: Please help if your able too:
public void clickButton(View view){
button = (Button) findViewById(R.id.button);
drawDate = (TextView)findViewById(R.id.drawDate);
LotteryAPI.Factory.getIstance().getLottery().enqueue(new Callback<Lottery>() {
#Override
public void onResponse(Call<Lottery> call, Response<Lottery> response) {
Log.d(TAG, "getting Draw Date");
Log.d(TAG, "Draw Date is: " + response.body().getDrawDate());
String DRAW_DATE = response.body().getDrawDate();
drawDate.setText("DRAW_DATE");
Log.d(TAG, "done setting Draw Date");
}
#Override
public void onFailure(Call<Lottery> call, Throwable t) {
Log.e("Failed", t.getMessage());
Log.d(TAG, "At onFailure - Something Failed!!");
Log.d(TAG, "error is: " + t.getCause());
}
});
}
Here is my interface:
String BASE_URL = "https://data.ny.gov/resource/h6w8-42p9.json/";
#GET("?$$app_token=xxxxxxGtxKw3s6gurSxxxxxx")
Call<Lottery> getLottery();
class Factory {
public static LotteryAPI service;
public static LotteryAPI getIstance() {
if (service == null) {
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()).baseUrl(BASE_URL).build();
service = retrofit.create(LotteryAPI.class);
return service;
} else {
return service;
}
}
}
Here is my POJO:
#Generated("org.jsonschema2pojo")
public class Lottery {
#SerializedName("draw_date")
#Expose
private String drawDate;
#SerializedName("mega_ball")
#Expose
private String megaBall;
#SerializedName("multiplier")
#Expose
private String multiplier;
#SerializedName("winning_numbers")
#Expose
private String winningNumbers;
/**
*
* #return
* The drawDate
*/
public String getDrawDate() {
return drawDate;
}
/**
*
* #param drawDate
* The draw_date
*/
public void setDrawDate(String drawDate) {
this.drawDate = drawDate;
}
/**
*
* #return
* The megaBall
*/
public String getMegaBall() {
return megaBall;
}
/**
*
* #param megaBall
* The mega_ball
*/
public void setMegaBall(String megaBall) {
this.megaBall = megaBall;
}
/**
*
* #return
* The multiplier
*/
public String getMultiplier() {
return multiplier;
}
/**
*
* #param multiplier
* The multiplier
*/
public void setMultiplier(String multiplier) {
this.multiplier = multiplier;
}
/**
*
* #return
* The winningNumbers
*/
public String getWinningNumbers() {
return winningNumbers;
}
/**
*
* #param winningNumbers
* The winning_numbers
*/
public void setWinningNumbers(String winningNumbers) {
this.winningNumbers = winningNumbers;
}
}
The problem is that the endpoint is returning a list of your Lottery class items and you are asking Retrofit to map the response to a single Lottery item.
Try changing Call<Lottery> getLottery(); to Call<List<Lottery>> getLottery();. You will also need to change it in your Retrofit call definition.
You should change the structure of POJO class structure, because as i can see your json string is an array which contain objects. You have to make to POJO classes:
class Lottery {
private String draw_date, mega_ball, multiplier, winning_numbers;
public Lottery() {}
public String getDraw_date() {
return draw_date;
}
public void setDraw_date(String draw_date) {
this.draw_date = draw_date;
}
public String getWinning_numbers() {
return winning_numbers;
}
public void setWinning_numbers(String winning_numbers) {
this.winning_numbers = winning_numbers;
}
public String getMega_ball() {
return mega_ball;
}
public void setMega_ball(String mega_ball) {
this.mega_ball = mega_ball;
}
public String getMultiplier() {
return multiplier;
}
public void setMultiplier(String multiplier) {
this.multiplier = multiplier;
}
}
You also have to change the following line into LotteryAPI interface from
Call<Lottery> getLottery();
to
Call<List<Lottery>> getLottery();
Then inside onResponse() callback you should iterate through the LotteryObj list
public void clickButton(View view){
button = (Button) findViewById(R.id.button);
drawDate = (TextView)findViewById(R.id.drawDate);
LotteryAPI.Factory.getIstance().getLottery().enqueue(new Callback<List<Lottery>>() {
#Override
public void onResponse(Response<List<Lottery>> response, Retrofit retrofit) {
Log.e(TAG, response.body()+"");
for (Lottery lt : response.body()) {
Log.e(TAG, lt.getDraw_date());
Log.e(TAG, lt.getMega_ball());
if (lt.getMultiplier() != null) Log.e(TAG, lt.getMultiplier());
Log.e(TAG, lt.getWinning_numbers());
}
Log.d(TAG, "getting Draw Date");
// Log.d(TAG, "Draw Date is: " + response.body().getDrawDate());
// String DRAW_DATE = response.body().getDrawDate();
drawDate.setText("DRAW_DATE");
Log.d(TAG, "done setting Draw Date");
}
#Override
public void onFailure(Throwable t) {
Log.e("Failed", t.getMessage());
Log.d(TAG, "At onFailure - Something Failed!!");
Log.d(TAG, "error is: " + t.getCause());
}
});
}
am not able to make SFtp download continuously....0 Kb files are getting downloaded in between..i have used VFS2. Though the same happens in windows, once I refresh the folder,the files are getting filled....but not in Ubuntu...can someone help me with this..
package com.softwareag.webmastersperformer.common.model;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.softwareag.webmastersperformer.common.exception.ActionExecutionFailedException;
import com.softwareag.webmastersperformer.common.exception.InvalidDataException;
/**
* This class extends from AbstractAction by providing specific implementation
* for SFTP action type.
* #author : YEJ
*/
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder = {
"fileTransferMethod", "serverHostName", "serverSFTPPort",
"serverRelativePath", "fileName", "localFilePath", "basicSettings",
"advancedSettings"
})
public class SftpAction implements IAction {
private String fileTransferMethod;
private String serverHostName;
private int serverSFTPPort;
private String serverRelativePath;
private String fileName;
private String localFilePath;
#XmlJavaTypeAdapter(GenericMapAdapter.class)
private Map<String, Object> basicSettings;
#XmlJavaTypeAdapter(GenericMapAdapter.class)
private Map<String, Object> advancedSettings;
#XmlTransient
private ActionBean parent;
#XmlTransient
private static final Logger LOG = LoggerFactory.getLogger(SftpAction.class
.getName());
#XmlTransient
private FileObject localFile;
#XmlTransient
private FileObject remoteFile;
#XmlTransient
private static StandardFileSystemManager manager;
#XmlTransient
private int i = 0;
// Initializing file manager. This manager object is made one per class as
// we
// cannot have more than one instance of this class instance.
static {
try {
manager = new StandardFileSystemManager();
manager.init();
} catch (FileSystemException ex) {
// Need to log this properly
ex.printStackTrace();
}
}
/**
* Constructor.
*/
public SftpAction() {
super();
this.fileTransferMethod = "put";
this.serverHostName = "";
this.serverSFTPPort = 0;
this.serverRelativePath = "";
this.fileName = "";
this.localFilePath = "";
}
/**
* Constructor.
* #param parent : ActionBean
* #param fileTransferMethod : File transfer method [put/get]
* #param serverHostName : server host name
* #param serverSFTPPort : server SFTP port
* #param localFilePath : local file path
* #throws InvalidDataException : file transfer method is not given
*/
// CHECKSTYLE:OFF
public SftpAction(final ActionBean parent, final String fileTransferMethod,
final String serverHostName, final int serverSFTPPort,
final String serverRelativeFtpPath, final String fileName,
final String localFilePath, final Map<String, Object> basicSettings)
throws InvalidDataException {
// CHECKSTYLE:ON
if (fileTransferMethod == null
|| fileTransferMethod.trim().length() == 0) {
throw new InvalidDataException(
"File transfer method cannot be null or empty");
}
System.out.println("================================================SFTPACTION() " + serverHostName);
this.setParent(parent);
this.setFileTransferMethod(fileTransferMethod);
this.setServerHostName(serverHostName);
this.setServerSFTPPort(serverSFTPPort);
this.setServerRelativePath(serverRelativeFtpPath);
this.setFileName(fileName);
this.setLocalFilePath(localFilePath);
this.setBasicSettings(basicSettings);
this.createClient();
}
/**
* Create a client.
* #throws InvalidDataException : InvalidDataException
*/
public final void createClient() throws InvalidDataException {
try {
if (fileTransferMethod.equalsIgnoreCase("put")) {
final File file = new File(this.localFilePath + File.separator
+ this.fileName);
if (!file.exists()) {
throw new RuntimeException("Error: Local file "
+ file.getAbsolutePath() + " not found");
}
try {
// Put : Create local file object
localFile = manager.resolveFile(file.getAbsolutePath());
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
// Get : Create remote file object
// remoteFile = manager.resolveFile(
// createConnectionString(
// (this.serverHostName + ":" + this.serverSFTPPort), this
// .getBasicSettings().get(Constants.USERNAME)
// .toString(),
// this.getBasicSettings().get(Constants.PASSWORD)
// .toString(), (this.serverRelativePath
// + File.separator + this.fileName)),
// createDefaultOptions());
remoteFile = manager.resolveFile(
createConnectionString(
"10.60.24.218:9876", "perfuser", "manage", ("1MB.txt")),
createDefaultOptions());
}
} catch (FileSystemException ex) {
ex.printStackTrace();
}
}
/**
* {#inheritDoc}
*/
#Override
public final boolean execute() throws ActionExecutionFailedException {
if (getFileTransferMethod().equalsIgnoreCase("put")) {
this.put();
} else {
this.get();
}
return true;
}
// Method to upload a file in Remote server
public void put() {
try {
// Create remote file object
remoteFile = manager
.resolveFile(
createConnectionString(
(this.serverHostName + ":" + this.serverSFTPPort), this
.getBasicSettings().get(Constants.USERNAME)
.toString(),
this.getBasicSettings().get(Constants.PASSWORD)
.toString(), (this.serverRelativePath + "/"
+ this.fileName + "_" + i++)),
createDefaultOptions());
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Download file function:
public void get() {
try {
String downloadFilePath = this.localFilePath + File.separator
+ this.fileName + "_" + i++;
// Create local file object
localFile = manager.resolveFile(downloadFilePath);
// Copy local file to sftp server
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* {#inheritDoc}
*/
#Override
public final ActionBean getParent() {
return this.parent;
}
/**
* #return the fileTransferMethod
*/
public final String getFileTransferMethod() {
return this.fileTransferMethod;
}
/**
* #return the serverHostName
*/
public final String getServerHostName() {
return this.serverHostName;
}
public final int getServerSFTPPort() {
return this.serverSFTPPort;
}
/**
* #return the localFilePath
*/
public final String getLocalFilePath() {
return this.localFilePath;
}
/**
* #return the local file name
*/
public final String getFileName() {
return this.fileName;
}
/**
* {#inheritDoc}
*/
#Override
public final String getActionName() {
return this.parent.getActionName();
}
/**
* {#inheritDoc}
*/
#Override
public final String getActionDescription() {
return this.parent.getDescription();
}
/**
* {#inheritDoc}
*/
#Override
public final ActionType getActionType() {
return this.parent.getActionType();
}
#Override
public final Map<String, Object> getBasicSettings() {
return this.basicSettings;
}
#Override
public final Map<String, Object> getAdvancedSettings() {
return this.advancedSettings;
}
#Override
public final Map<String, ArrayList<String>> getParameterisedData() {
// TODO Auto-generated method stub
return null;
}
#Override
public final String getPayloadData() throws IOException {
// TODO Auto-generated method stub
return null;
}
#Override
public final RequestResponseHolder getRequestResponse()
throws ActionExecutionFailedException {
// TODO Auto-generated method stub
return null;
}
#Override
public void addParameter(final String parameterName,
final ArrayList<String> parameterValues) {
// TODO Auto-generated method stub
}
/**
* {#inheritDoc}
*/
#Override
public final void setParent(final ActionBean action)
throws InvalidDataException {
if (null == action) {
throw new InvalidDataException(
"Invalid Parent. ActionBean cannot be null");
}
this.parent = action;
}
/**
* #param fileTransferMethod : file transfer method to set
* #throws InvalidDataException if file transfer method is null or empty
*/
public final void setFileTransferMethod(final String fileTransferMethod)
throws InvalidDataException {
this.fileTransferMethod = fileTransferMethod;
}
/**
* #param serverURL : the server URL to set
* #throws InvalidDataException if server URL is null or empty
*/
public final void setServerHostName(String serverURL)
throws InvalidDataException {
serverURL = "10.60.24.218:9876";
if (serverURL == null || serverURL.trim().length() == 0) {
throw new InvalidDataException("Server URL cannot be null or empty");
}
this.serverHostName = serverURL;
}
public final void setServerSFTPPort(final int serverSFTPPort) {
this.serverSFTPPort = serverSFTPPort;
}
/**
* #param localFilePath : local file path to set
* #throws InvalidDataException if local file null or empty
*/
public final void setLocalFilePath(final String localFilePath)
throws InvalidDataException {
if (localFilePath == null || localFilePath.trim().length() == 0
/* || !(new File(localFilePath).exists()) */) {
throw new InvalidDataException(
"Local file path cannot be null or empty or invalid");
}
this.localFilePath = localFilePath;
}
#Override
public final void setBasicSettings(final Map<String, Object> basicSettings)
throws InvalidDataException {
this.basicSettings = basicSettings;
}
#Override
public final void setAdvancedSettings(
final Map<String, Object> advancedSettings) {
this.advancedSettings = advancedSettings;
}
#Override
public void setPayload(final String payload) throws InvalidDataException {
// TODO Auto-generated method stub
}
#Override
public void modifyURL(final String newHost, final int newPort)
throws InvalidDataException {
// TODO Auto-generated method stub
}
/**
* This method is used to set the new file name from the parameter file for
* each action.
* #param newFileName : new file name
*/
public final void setFileName(final String newFileName) {
this.fileName = newFileName;
}
/**
* {#inheritDoc}
*/
#Override
public final SftpAction copyAction() {
/*
* Cloning the action Note: Cloned action will not contain parameterized
* map
*/
SftpAction clonedAction = null;
try {
clonedAction = new SftpAction();
clonedAction.setParent(this.getParent());
clonedAction.setFileTransferMethod(this.getFileTransferMethod());
clonedAction.setServerHostName(this.getServerHostName());
clonedAction.setServerSFTPPort(this.getServerSFTPPort());
clonedAction.setServerRelativePath(this.getServerRelativePath());
clonedAction.setFileName(this.getFileName());
clonedAction.setLocalFilePath(this.getLocalFilePath());
clonedAction.setBasicSettings(this.getBasicSettings());
} catch (InvalidDataException e) {
e.printStackTrace();
LOG.error(e.getMessage());
}
return clonedAction;
}
/**
* {#inheritDoc}
*/
#Override
public void stopExecution() {
// nothing to do
}
/**
* {#inheritDoc}
*/
#Override
public final void shutdown() {
if (this.manager != null) {
this.manager.close();
}
}
public String getServerRelativePath() {
return serverRelativePath;
}
public void setServerRelativePath(String serverRelativePath) {
this.serverRelativePath = serverRelativePath;
}
// Establishing connection
private String createConnectionString(String hostName, String username,
String password, String remoteFilePath) {
return "sftp://" + username + ":" + password + "#" + hostName + "/"
+ remoteFilePath;
}
// Method to setup default SFTP config:
private FileSystemOptions createDefaultOptions() throws FileSystemException {
// Create SFTP options
FileSystemOptions opts = new FileSystemOptions();
// SSH Key checking
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(
opts, "no");
// Root directory set to user home
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
// Timeout is count by Milliseconds
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
return opts;
}
}
I tried to save data to json string in a txt file using Gson and then restore it using Gson either. Things go well if I do it in eclipse. But when packaged to jar, Gson throws Exceptions.
Here is the code for saving the file.
String gsonStr = gson.toJson(masterShips); // masterShips is ArrayList<Ship>
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter("D:\\master_ship.txt"));
writer.write(gsonStr);
} catch (IOException e) {
System.err.println(e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
Then I read the file in eclipse using this code (and it works):
Scanner in = new Scanner(new FileReader("D:\\master_ship.txt"));
String str = in.nextLine();
Log.toDebug(str);
in.close();
JsonParser parser = new JsonParser();
JsonElement je = parser.parse(str);
JsonArray ja = je.getAsJsonArray();
for (int i=0; i<ja.size(); ++i) {
...
}
But after packaged into jar and run in cmd, Exception occurs:
Exception in thread "main" com.google.gson.JsonSyntaxException: com.google.gson.
stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malform
ed JSON at line 1 column 4
at com.google.gson.JsonParser.parse(JsonParser.java:65)
at com.google.gson.JsonParser.parse(JsonParser.java:45)
at kan.util.Master.loadMasterShip(Master.java:44)
at kan.util.Master.load(Master.java:27)
at kan.Main.main(Main.java:22)
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLeni
ent(true) to accept malformed JSON at line 1 column 4
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1505)
at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1386)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:531)
at com.google.gson.stream.JsonReader.peek(JsonReader.java:414)
at com.google.gson.JsonParser.parse(JsonParser.java:60)
... 4 more
According to the hint of the Exception, I changed my code and it still works in eclipse:
Scanner in = new Scanner(new FileReader("D:\\master_ship.txt"));
String str = in.nextLine();
in.close();
Reader reader = new StringReader(str);
JsonReader jr = new JsonReader(reader);
jr.setLenient(true);
JsonParser parser = new JsonParser();
JsonElement je = parser.parse(jr);
JsonArray ja = je.getAsJsonArray();
for (int i=0; i<ja.size(); ++i) {
...
}
But jar failed and throws
Exception in thread "main" java.lang.IllegalStateException: This is not a JSON A
rray.
at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:106)
at kan.util.Master.loadMasterShip(Master.java:58)
at kan.util.Master.load(Master.java:30)
at kan.Main.main(Main.java:22)
As suggested by Sotirios I cut the length of the arraylist down, and when I increase the number of ships to 4, things go wrong. Here is the json:
[{"id":1,"name":"睦月","type":2,"rank":2,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":254,"range":1,"powerups":[1,1,0,0]},{"id":2,"name":"如月","type":2,"rank":1,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":255,"range":1,"powerups":[0,1,0,0]},{"id":6,"name":"長月","type":2,"rank":1,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":258,"range":1,"powerups":[0,1,0,0]},{"id":7,"name":"三日月","type":2,"rank":1,"fuelMax":15,"bulletMax":15,"slotNum":2,"speed":10,"afterLv":20,"afterId":260,"range":1,"powerups":[0,1,0,0]}]
↑ colunm 473
Exception in thread "main" com.google.gson.JsonSyntaxException: com.google.gson.
stream.MalformedJsonException: Unterminated object at line 1 column 473
at com.google.gson.internal.Streams.parse(Streams.java:56)
at com.google.gson.JsonParser.parse(JsonParser.java:84)
at kan.util.Master.loadMasterShip(Master.java:55)
at kan.util.Master.load(Master.java:30)
at kan.Main.main(Main.java:22)
Caused by: com.google.gson.stream.MalformedJsonException: Unterminated object at
line 1 column 473
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1505)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:480)
at com.google.gson.stream.JsonReader.hasNext(JsonReader.java:403)
at com.google.gson.internal.bind.TypeAdapters$25.read(TypeAdapters.java:
666)
at com.google.gson.internal.bind.TypeAdapters$25.read(TypeAdapters.java:
659)
at com.google.gson.internal.bind.TypeAdapters$25.read(TypeAdapters.java:
642)
at com.google.gson.internal.Streams.parse(Streams.java:44)
... 4 more
Can anyone help me with this, you will be reaally preciated!
Use this class
import java.util.List;
public class GsonResponse
{
public int id;
public String name;
public int type;
public int rank;
public int fuelMax;
public int bulletMax;
public int slotNum;
public int speed;
public int afterLv;
public int afterId;
public int range;
public List<Integer> powerups;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the type
*/
public int getType() {
return type;
}
/**
* #param type the type to set
*/
public void setType(int type) {
this.type = type;
}
/**
* #return the rank
*/
public int getRank() {
return rank;
}
/**
* #param rank the rank to set
*/
public void setRank(int rank) {
this.rank = rank;
}
/**
* #return the fuelMax
*/
public int getFuelMax() {
return fuelMax;
}
/**
* #param fuelMax the fuelMax to set
*/
public void setFuelMax(int fuelMax) {
this.fuelMax = fuelMax;
}
/**
* #return the bulletMax
*/
public int getBulletMax() {
return bulletMax;
}
/**
* #param bulletMax the bulletMax to set
*/
public void setBulletMax(int bulletMax) {
this.bulletMax = bulletMax;
}
/**
* #return the slotNum
*/
public int getSlotNum() {
return slotNum;
}
/**
* #param slotNum the slotNum to set
*/
public void setSlotNum(int slotNum) {
this.slotNum = slotNum;
}
/**
* #return the speed
*/
public int getSpeed() {
return speed;
}
/**
* #param speed the speed to set
*/
public void setSpeed(int speed) {
this.speed = speed;
}
/**
* #return the afterLv
*/
public int getAfterLv() {
return afterLv;
}
/**
* #param afterLv the afterLv to set
*/
public void setAfterLv(int afterLv) {
this.afterLv = afterLv;
}
/**
* #return the afterId
*/
public int getAfterId() {
return afterId;
}
/**
* #param afterId the afterId to set
*/
public void setAfterId(int afterId) {
this.afterId = afterId;
}
/**
* #return the range
*/
public int getRange() {
return range;
}
/**
* #param range the range to set
*/
public void setRange(int range) {
this.range = range;
}
/**
* #return the powerups
*/
public List<Integer> getPowerups() {
return powerups;
}
/**
* #param powerups the powerups to set
*/
public void setPowerups(List<Integer> powerups) {
this.powerups = powerups;
}
}
just add below code where u parse
String strJson = "[{\"id\":1,\"name\":\"睦月\",\"type\":2,\"rank\":2,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":254,\"range\":1,\"powerups\":[1,1,0,0]},{\"id\":2,\"name\":\"如月\",\"type\":2,\"rank\":1,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":255,\"range\":1,\"powerups\":[0,1,0,0]},{\"id\":6,\"name\":\"長月\",\"type\":2,\"rank\":1,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":258,\"range\":1,\"powerups\":[0,1,0,0]},{\"id\":7,\"name\":\"三日月\",\"type\":2,\"rank\":1,\"fuelMax\":15,\"bulletMax\":15,\"slotNum\":2,\"speed\":10,\"afterLv\":20,\"afterId\":260,\"range\":1,\"powerups\":[0,1,0,0]}]";
GsonResponse gsonResponse = null;
try {
gsonResponse = new Gson().fromJson(strJson,
GsonResponse.class);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}