Skip to content

Commit

Permalink
refactor: Type inference hack for fromJson
Browse files Browse the repository at this point in the history
  • Loading branch information
SMadani committed Nov 1, 2023
1 parent 84b2567 commit 8718d8a
Show file tree
Hide file tree
Showing 55 changed files with 103 additions and 83 deletions.
49 changes: 49 additions & 0 deletions src/main/java/com/vonage/client/Jsonable.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,23 @@
*/
public interface Jsonable {

/**
* Convenience method for creating an ObjectMapper with standard settings.
*
* @return A new ObjectMapper with appropriate configuration.
*/
static ObjectMapper createDefaultObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
return mapper;
}

/**
* Serialises this class to a JSON payload.
*
* @return The JSON string representing this class's marked properties.
*/
default String toJson() {
try {
return createDefaultObjectMapper().writeValueAsString(this);
Expand All @@ -45,6 +55,13 @@ default String toJson() {
}
}

/**
* Updates this class's fields from the JSON payload.
*
* @param json The JSON string.
*
* @throws VonageResponseParseException If the JSON was invalid or this class couldn't be updated.
*/
default void updateFromJson(String json) {
if (json == null || json.trim().isEmpty()) {
return;
Expand All @@ -57,6 +74,38 @@ default void updateFromJson(String json) {
}
}

/**
* Delegates to {@linkplain #fromJson(String, Class)}, using the type varargs for inferring the class.
*
* @param json The JSON string to parse.
* @param type Unused. This is a hack to get the array class's component type.
*
* @return A new instance of the inferred Jsonable.
*
* @param <J> A class which implements this interface.
*
* @throws VonageUnexpectedException If a no-args constructor for the class was not found.
* @throws VonageResponseParseException If the JSON was invalid or this class couldn't be updated.
*/
@SuppressWarnings("unchecked")
static <J extends Jsonable> J fromJson(String json, J... type) {
return fromJson(json, (Class<J>) type.getClass().getComponentType());
}

/**
* Creates a new instance of the designated Jsonable class, calling its no-args constructor
* followed by {@link #updateFromJson(String)}.
*
* @param json The JSON string to parse.
* @param jsonable The Jsonable class to construct.
*
* @return A new instance of the Jsonable class.
*
* @param <J> A class which implements this interface.
*
* @throws VonageUnexpectedException If a no-args constructor for the class was not found.
* @throws VonageResponseParseException If the JSON was invalid or this class couldn't be updated.
*/
static <J extends Jsonable> J fromJson(String json, Class<? extends J> jsonable) {
try {
Constructor<? extends J> constructor = jsonable.getDeclaredConstructor();
Expand Down
20 changes: 1 addition & 19 deletions src/main/java/com/vonage/client/VonageApiResponseException.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -219,21 +216,6 @@ protected static <E extends VonageApiResponseException> E fromJson(Class<E> claz
throw new VonageUnexpectedException(ex);
}
}
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, clazz);
}
catch (IOException ex) {
throw new VonageResponseParseException("Failed to produce "+clazz.getSimpleName()+" from json.", ex);
}
}

protected static <E extends VonageApiResponseException> E fromHttpResponse(Class<E> clazz, HttpResponse response) throws IOException {
E crx = fromJson(clazz, EntityUtils.toString(response.getEntity()));
if (crx.title == null) {
crx.title = response.getStatusLine().getReasonPhrase();
}
crx.statusCode = response.getStatusLine().getStatusCode();
return crx;
else return Jsonable.fromJson(json, clazz);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ public boolean isAutoReload() {
}

public static BalanceResponse fromJson(String json) {
return Jsonable.fromJson(json, BalanceResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ public void updateFromJson(String json) {
}

public static ListSecretsResponse fromJson(String json) {
return Jsonable.fromJson(json, ListSecretsResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ public List<PricingResponse> getCountries() {
}

public static PrefixPricingResponse fromJson(String json) {
return Jsonable.fromJson(json, PrefixPricingResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ public List<Network> getNetworks() {
}

public static PricingResponse fromJson(String json) {
return Jsonable.fromJson(json, PricingResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ public void updateFromJson(String json) {
}

public static SecretResponse fromJson(String json) {
return Jsonable.fromJson(json, SecretResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ public Integer getMaxApiCallsPerSecond() {
}

public static SettingsResponse fromJson(String json) {
return Jsonable.fromJson(json, SettingsResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public Privacy getPrivacy() {
}

public static Application fromJson(String json) {
return Jsonable.fromJson(json, Application.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ public List<Application> getApplications() {
}

public static ApplicationList fromJson(String json) {
return Jsonable.fromJson(json, ApplicationList.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/incoming/CallEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ public CallStatusDetail getDetailEnum() {
}

public static CallEvent fromJson(String json) {
return Jsonable.fromJson(json, CallEvent.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/incoming/InputEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,6 @@ public SpeechResults getSpeech() {
}

public static InputEvent fromJson(String json) {
return Jsonable.fromJson(json, InputEvent.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/incoming/MessageEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,6 @@ public void updateFromJson(String json) {
}

public static MessageEvent fromJson(String json) {
return Jsonable.fromJson(json, MessageEvent.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/incoming/NotifyEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ public String toString() {
}

public static NotifyEvent fromJson(String json) {
return Jsonable.fromJson(json, NotifyEvent.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/incoming/RecordEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ public Date getTimestamp() {
}

public static RecordEvent fromJson(String json) {
return Jsonable.fromJson(json, RecordEvent.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class AdvancedInsightResponse extends StandardInsightResponse {
private String errorText;

public static AdvancedInsightResponse fromJson(String json) {
return Jsonable.fromJson(json, AdvancedInsightResponse.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class BasicInsightResponse implements Jsonable {
countryCode, countryCodeIso3, countryName, countryPrefix;

public static BasicInsightResponse fromJson(String json) {
return Jsonable.fromJson(json, BasicInsightResponse.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class StandardInsightResponse extends BasicInsightResponse {
private CallerType callerType;

public static StandardInsightResponse fromJson(String json) {
return Jsonable.fromJson(json, StandardInsightResponse.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/meetings/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ public UUID getDefaultThemeId() {
* @return An instance of this class with the fields populated, if present.
*/
public static Application fromJson(String json) {
return Jsonable.fromJson(json, Application.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public List<Recording> getRecordings() {
}

public static ListRecordingsResponse fromJson(String json) {
return Jsonable.fromJson(json, ListRecordingsResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ public List<MeetingRoom> getMeetingRooms() {
* @return An instance of this class with the fields populated, if present.
*/
public static ListRoomsResponse fromJson(String json) {
return Jsonable.fromJson(json, ListRoomsResponse.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/meetings/MeetingRoom.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public RoomLinks getLinks() {
* @return An instance of this class with the fields populated, if present.
*/
public static MeetingRoom fromJson(String json) {
return Jsonable.fromJson(json, MeetingRoom.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,6 @@ public Boolean getIsHost() {
* @throws VonageResponseParseException If the response could not be deserialized.
*/
public static MeetingsEventCallback fromJson(String json) {
return Jsonable.fromJson(json, MeetingsEventCallback.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/meetings/Recording.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,6 @@ public URI getUrl() {
* @return An instance of this class with the fields populated, if present.
*/
public static Recording fromJson(String json) {
return Jsonable.fromJson(json, Recording.class);
return Jsonable.fromJson(json);
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/vonage/client/meetings/Theme.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public String toJson() {
* @return An instance of this class with the fields populated, if present.
*/
public static Theme fromJson(String json) {
return Jsonable.fromJson(json, Theme.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,6 @@ public SmsInboundMetadata getSmsMetadata() {
* @throws com.vonage.client.VonageResponseParseException If the response could not be deserialized.
*/
public static InboundMessage fromJson(String json) {
return Jsonable.fromJson(json, InboundMessage.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ public String toString() {
* @return An instance of this class with the fields populated, if present.
*/
public static MessageResponse fromJson(String json) {
return Jsonable.fromJson(json, MessageResponse.class);
return Jsonable.fromJson(json);
}
}
13 changes: 1 addition & 12 deletions src/main/java/com/vonage/client/messages/MessageStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@
package com.vonage.client.messages;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.vonage.client.Jsonable;
import com.vonage.client.VonageUnexpectedException;
import java.io.IOException;
import java.net.URI;
import java.time.Instant;
import java.util.Currency;
Expand Down Expand Up @@ -304,14 +300,7 @@ public Usage getUsage() {
* @return An instance of this class with the fields populated, if present.
*/
public static MessageStatus fromJson(String json) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper.readValue(json, MessageStatus.class);
}
catch (IOException ex) {
throw new VonageUnexpectedException("Failed to produce MessageStatus from json.", ex);
}
return Jsonable.fromJson(json);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ public OwnedNumber[] getNumbers() {
}

public static ListNumbersResponse fromJson(String json) {
return Jsonable.fromJson(json, ListNumbersResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public AvailableNumber[] getNumbers() {
}

public static SearchNumbersResponse fromJson(String json) {
return Jsonable.fromJson(json, SearchNumbersResponse.class);
return Jsonable.fromJson(json);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public SyncStatus getSyncStatus() {
* @return An instance of this class with the fields populated, if present.
*/
public static ContactsList fromJson(String json) {
return Jsonable.fromJson(json, ContactsList.class);
return Jsonable.fromJson(json);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,6 @@ public EventType getType() {
* @return An instance of this class with the fields populated, if present.
*/
public static Event fromJson(String json) {
return Jsonable.fromJson(json, Event.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ public List<Event> getEvents() {
* @return An instance of this class with the fields populated, if present.
*/
public static ListEventsResponse fromJson(String json) {
return Jsonable.fromJson(json, ListEventsResponse.class);
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@ public UUID getListId() {
* @return An instance of this class with the fields populated, if present.
*/
public static ListItem fromJson(String json) {
return Jsonable.fromJson(json, ListItem.class);
return Jsonable.fromJson(json);
}
}
Loading

0 comments on commit 8718d8a

Please sign in to comment.