Adding information from one JsonBuilder object to another - json

As the title suggests, I'm trying to add information held in one JsonBuilder object to a second JsonBuilder object.
Currently I have this:
public String buildOneUser(DyveUserDTO user)
{
def userBuilder = new JsonBuilder()
userBuilder user.collect { usr ->
[
'Name': usr.userName,
'Allowance': usr.allowance,
'Total Holidays in Calendar': usr.totalHolidaysInCal,
'Holidays Booked': usr.numHolidaysBooked,
'Holidays Taken': usr.numHolidaysTaken,
'Holidays Remaining': usr.totalHolidaysLeft
]
}
def userHolidayBuilder = new JsonBuilder()
userHolidayBuilder user.holidayEvents.collect { usr ->
[
'Start Date': usr.startDate,
'End Date': usr.endDate,
'Days': usr.days
]
}
def userAndHolidays = userBuilder + userHolidayBuilder
return userAndHolidays.toPrettyString()
}
user.holidayEvents is a list of objects representing holidays and it could be empty or have any number of objects in it. This made me hesitant of doing something like:
def userBuilder = new JsonBuilder()
userBuilder user.collect { usr ->
[
'Name': usr.userName,
'Allowance': usr.allowance,
'Total Holidays in Calendar': usr.totalHolidaysInCal,
'Holidays Booked': usr.numHolidaysBooked,
'Holidays Taken': usr.numHolidaysTaken,
'Holidays Remaining': usr.totalHolidaysLeft
'Holiday': usr.holidayEvents[0].startDate
'Holiday': usr.holidayEvents[0].endDate
'Holiday': usr.holidayEvents[0].days
]
}
As I would only get the amount of holidays I write code for. It would also throw an exception if a user had no holidays and I told it look at usr.holidayEvents[1] as it's outside of the list range.
I've also tried nesting a .collect like this
def userBuilder = new JsonBuilder()
userBuilder {
'Name' user.userName,
'Allowance' user.allowance,
'Total Holidays in Calendar' user.totalHolidaysInCal,
'Holidays Booked' user.numHolidaysBooked,
'Holidays Taken' user.numHolidaysTaken,
'Holidays Remaining' user.totalHolidaysLeft,
'Holidays' user.holidayEvents.collect{ evt ->
[
'Start Date': evt.startDate,
'End Date': evt.endDate,
'Days': evt.days
]
}
}
But this returned all the keys except the Holidays key.
Any help would be greatly appreciated!
EDIT - My code now looks like this:
public String buildOneUser(DyveUserDTO user)
{
def userBuilder = new JsonBuilder()
userBuilder user.collect { usr ->
[
'Name': usr.userName,
'Allowance': usr.allowance,
'Total Holidays in Calendar': usr.totalHolidaysInCal,
'Holidays Booked': usr.numHolidaysBooked,
'Holidays Taken': usr.numHolidaysTaken,
'Holidays Remaining': usr.totalHolidaysLeft,
'Holidays': usr.holidayEvents.collect{ evt ->
[
'Start Date': evt.startDate,
'End Date': evt.endDate,
'Days': evt.days
]
}
]
}
}
EDIT 2 - Sample Code
Method to call:
public String buildOneUser(DyveUserDTO user)
{
def userBuilder = new JsonBuilder()
userBuilder {
Name:
user.userName
Allowance:
user.allowance
TotalHolidaysInCalendar:
user.totalHolidaysInCal
HolidaysBooked:
user.numHolidaysBooked
HolidaysTaken:
user.numHolidaysTaken
HolidaysRemaining:
user.totalHolidaysLeft
Holidays:
user.holidayEvents.collect { evt ->
[
'Start Date': evt.startDate,
'End Date' : evt.endDate,
'Days' : evt.days
]
}
}
return userBuilder.toPrettyString()
}
User to pass in:
class DyveUserDTO
{
String firstName = "Foo"
String userName = "FooBar"
Integer userID = 42
BigDecimal numHolidaysBooked = 3
BigDecimal numHolidaysTaken = 0
BigDecimal totalHolidaysInCal = 3
BigDecimal totalHolidaysLeft = 12
BigDecimal allowance = 12
List<HolidayObject> holidayEvents = []
}
Holiday objects to go in holidayEvents:
class HolidayObject
{
public Integer userID = 42
public String title = "Foo Holiday"
public String event = "Holiday"
public String amPm = "Full Day"
public String name = "Foo"
public LocalDateTime startDate = LocalDateTime.parse(2015-02-20T00:00:00)
public LocalDateTime endDate = LocalDateTime.parse(2015-02-20T00:00:00)
public BigDecimal days = 1
}
class HolidayObject
{
public Integer userID = 42
public String title = "Foo Holiday Pm"
public String event = "Holiday"
public String amPm = "Pm"
public String name = "Foo"
public LocalDateTime startDate = LocalDateTime.parse(2015-02-23T00:00:00)
public LocalDateTime endDate = LocalDateTime.parse(2015-02-24T00:00:00)
public BigDecimal days = 2
}

each just returns the list it's called upon, collect should be used for events. See the working code below:
import groovy.json.JsonBuilder
class UserEvent {
def start
def end
def days
}
class User {
def name
def events
}
def u1 = new User(name: 'u1', events: [new UserEvent(start: 0, end: 1, days: 1), new UserEvent(start: 0, end: 2, days: 2)])
def u2 = new User(name: 'u2', events: [new UserEvent(start: 0, end: 3, days: 3)])
def users = [u1, u2]
def userBuilder = new JsonBuilder()
userBuilder users.collect { usr ->
[
'name': usr.name,
'events': usr.events.collect { e ->
[
start: e.start,
end: e.end,
days: e.days,
]
}
]
}
print userBuilder.toPrettyString()
EDIT
Below is a working example:
import groovy.json.JsonBuilder
user = new DyveUserDTO()
def userBuilder = new JsonBuilder()
userBuilder {
Name user.userName
Allowance user.allowance
TotalHolidaysInCalendar user.totalHolidaysInCal
HolidaysBooked user.numHolidaysBooked
HolidaysTaken user.numHolidaysTaken
HolidaysRemaining user.totalHolidaysLeft
Holidays user.holidayEvents.collect { evt ->
[
'Start Date': evt.startDate,
'End Date' : evt.endDate,
'Days' : evt.days
]
}
}
println userBuilder.toPrettyString()
class DyveUserDTO {
String firstName = "Foo"
String userName = "FooBar"
Integer userID = 42
BigDecimal numHolidaysBooked = 3
BigDecimal numHolidaysTaken = 0
BigDecimal totalHolidaysInCal = 3
BigDecimal totalHolidaysLeft = 12
BigDecimal allowance = 12
List<HolidayObject> holidayEvents = [new HolidayObject(), new HolidayObject()]
}
class HolidayObject {
public Integer userID = 42
public String title = "Foo Holiday"
public String event = "Holiday"
public String amPm = "Full Day"
public String name = "Foo"
public String startDate = '2015-02-20T00:00:00'
public String endDate = '2015-02-20T00:00:00'
public BigDecimal days = 1
}
No colons : needed. See the sample here. Also I have no Joda dependency so replaced with String.

Related

Spring JPA Projection duplicates parent entity when fetching nested collection with JPQL

Quick explanation
While fetching a nested collection from a JPQL query it serializes one parent object for each nested object. The intended behavior would be serializing one single parent object with a single collection/set of objects.
Using Spring DATA/DATA REST
JPQ Query
#Query(
"""
select distinct ticketOrder.id as id, user.name as name, ticket as tickets from TicketOrder ticketOrder
inner join User user on user.id = ticketOrder.user.id
inner join Ticket ticket on ticket.ticketOrder.id = ticketOrder.id
where user.uid = :uid
"""
)
fun findByUserUid(uid: UUID, pageable: Pageable): Page<TicketOrderProjection>
Related Entity Classes
TicketOrder
class TicketOrder(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "order_id", nullable = false)
val id: Long? = null,
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(nullable = false)
val user: User,
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(nullable = false, updatable = false)
val raffle: Raffle? = null,
#OneToMany(mappedBy = "ticketOrder", cascade = [CascadeType.ALL], orphanRemoval = true, fetch = FetchType.LAZY)
var tickets: MutableList<Ticket> = mutableListOf(),
#OneToOne(fetch = FetchType.LAZY)
var transaction: Transaction?,
#CreationTimestamp
#Column(name = "created_at", updatable = false)
val createdAt: Timestamp? = null,
#UpdateTimestamp
#Column(name = "updated_at")
val updatedAt: Timestamp? = null,
#Column(name = "completed_at", nullable = true)
var completedAt: LocalDateTime? = null,
#Column
var checkoutCode: String? = null,
#Enumerated(EnumType.STRING)
#Column(name = "order_status", nullable = false)
var status: TicketOrderStatus
)
/* ... omitted for brevity */
Ticket
#Entity
class Ticket(
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "ticket_id", nullable = false)
val id: Long? = null,
#Column(name = "ticket_number", nullable = false, columnDefinition = "UNIQUE")
val ticketNumber: Int,
#ManyToOne
#JoinColumn
var ticketOrder: TicketOrder? = null,
#ManyToOne
#JoinColumn
var raffle: Raffle
)
User
class User(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id", nullable = false)
val id: Long? = null,
#Column(nullable = false)
val name: String,
#Column(nullable = false)
val phone: Long,
#Column(nullable = false)
val email: String,
#Column(nullable = false, updatable = false)
val uid: UUID = UUID.randomUUID(),
#CreationTimestamp
#Column(name = "created_at", updatable = false)
val createdAt: Timestamp? = null
)
Projections
TicketOrderProjection
#Projection(types = [TicketOrder::class])
interface TicketOrderProjection {
val id: Long
val name: String
val tickets: Set<TicketsProjection>
}
TicketsProjection
#Projection(types = [Ticket::class])
interface TicketsProjection {
#get:Value("#{target.id}")
val id: Int
}
Finally
Response at RestController
{
"content": [
{
"name": "Raphael Heizer",
"id": 10,
"tickets": [
{
"id": 21
}
]
},
{
"name": "Raphael Heizer",
"id": 10,
"tickets": [
{
"id": 22
}
]
},
{
"name": "Raphael Heizer",
"id": 10,
"tickets": [
{
"id": 23
}
]
}
],
"pageable": {
// omitted
}
Expected response
{
"content": [
{
"name": "Raphael Heizer",
"id": 10,
"tickets": [
{
"id": 21,
},
{
"id": 22
},
{
"id": 23
}
]
},
],
"pageable": {
// omitted
}

How to mark latest datetime from the list of multiple same day dates

Json list -
[
{
"date": "2022-10-10T09:53:40.835519+05:30",
"value": 10
},
{
"date": "2022-10-13T09:53:40.835519+05:30",
"value": 12
},
{
"date": "2022-10-13T10:53:40.835519+05:30",
"value": 15
},
{
"date": "2022-10-15T10:53:40.835519+05:30",
"value": 20
}
]
in above list if there are multiple dateTimes for same day ( ex. 2022-10-13 )
so how to mark 2022-10-13T10:53 date in object list as isLatestDateForSameDay=true as 2022-10-
13T10:53 is latest compare to 2022-10-13T09:53.
and if there is only one dateTime then it should also marked as isLatestDateForSameDay=true
ex. (2022-10-10T09:53:40.835519+05:30 and 2022-10-15T10:53:40.835519+05:30)
DataListItem class -
class DataListItem {
String date;
int value;
bool isLatestDate;
DataListItem({
required this.date,
required this.value,
this.isLatestDateForSameDay = false,
});
}
Expected list of Objects -
[
DataListItem(date: '2022-10-10T09:53:40.835519+05:30', value: 10, isLatestDateForSameDay: true),
DataListItem(date: '2022-10-13T09:53:40.835519+05:30', value: 12, isLatestDateForSameDay: false),
DataListItem(date: '2022-10-13T10:53:40.835519+05:30', value: 15, isLatestDateForSameDay: true),
DataListItem(date: '2022-10-15T10:53:40.835519+05:30', value: 20, isLatestDateForSameDay: true),
];
Lets assume your json is jsonData with collection package you can get what you want:
var grouped = groupBy(
jsonData,
(Map item) => (item['date'] as String).substring(0, 10),
);
List<DataListItem> result = [];
for (var element in grouped.entries) {
if (element.value.length == 1) {
result.add(DataListItem(
date: element.value.first['date'] as String,
value: element.value.first['value'] as int,
isLatestDate: true));
} else {
var latesItem = findLatestDate(element.value);
element.value.remove(latesItem);
result.add(DataListItem(
date: latesItem['date'] as String,
value: latesItem['value'] as int,
isLatestDate: true));
element.value.forEach((e) => result.add(DataListItem(
date: e['date'] as String,
value: e['value'] as int,
isLatestDate: false)));
}
}
Map<String, dynamic> findLatestDate(List<Map<String, dynamic>> dateList) {
Map<String, dynamic>? result;
for (var element in dateList) {
if (result == null) {
result = element;
} else {
DateTime resultDate =
DateFormat("yyyy-MM-ddThh:mm:ss").parse(result['date'] as String);
DateTime tempDate =
DateFormat("yyyy-MM-ddThh:mm:ss").parse(element['date'] as String);
if (tempDate.isAfter(resultDate)) {
result = element;
}
}
}
return result!;
}
for (var element in result) {
print("result= ${element.date} ${element.value} ${element.isLatestDate}");
// result= 2022-10-10T09:53:40.835519+05:30 10 true
// result= 2022-10-13T10:53:40.835519+05:30 15 true
// result= 2022-10-13T09:53:40.835519+05:30 12 false
// result= 2022-10-15T10:53:40.835519+05:30 20 true
}
also use intl for DateFormat.
Try sorting the list with DateTime.parse()
List<DataListItem> dataListItemlist = [];
list.sort(
(a, b) {
return DateTime.parse(a["date"]).compareTo(DateTime.parse(b["date"]));
},
);
List<String> repeatedDate = [];
for (var i = list.length - 1; i >= 0; i--) {
Map item = list[i];
DateTime date = DateTime.parse(item["date"]);
int day = date.day;
int month = date.month;
int year = date.year;
String formatedDate = "$day-$month-$year";
if (repeatedDate.contains(formatedDate)) {
dataListItemlist.add(
DataListItem(
date: item["date"],
value: item["value"],
isLatestDateForSameDay: false,
),
);
} else {
dataListItemlist.add(
DataListItem(
date: item["date"],
value: item["value"],
isLatestDateForSameDay: true,
),
);
repeatedDate.add(formatedDate);
}
}

Server side pagination in Graphql Scala

I need to do server side pagination in graphql in scala. I have seven reports and have used one graphql query with different operations to get the data. Now I need to add server side pagination to it and I am not able to do that. Any help would be appreciated. Below are my code:
Schema:
val PanelNominationStatusReportDataType = ObjectType(
"PanelNominationStatus",
"Dashboard Reports",
fields[Unit, PanelRewardSatusDetail](
Field("awardName", OptionType(StringType), resolve = _.value.awardName),
Field("nominatorEmail", OptionType(StringType), resolve = _.value.nominatorEmail),
Field("nomineeEmail", OptionType(StringType), resolve = _.value.nomineeEmail),
Field("nomineeLocation", OptionType(StringType), resolve = _.value.nomineeLocation),
Field("approverEmail", OptionType(StringType), resolve = _.value.approverEmail),
Field("citation", OptionType(StringType), resolve = _.value.citation),
Field("businessJustification", OptionType(StringType), resolve = _.value.businessJustification),
Field("rating", OptionType(IntType), resolve = _.value.rating),
Field("votingStatus", OptionType(StringType), resolve = _.value.votingStatus),
Field("nominatedDate", OptionType(StringType), resolve = _.value.nominatedDate),
Field("approvedDate", OptionType(StringType), resolve = _.value.approvedDate)
)
)
Graphql Query:
Field(
"PanelNominationStatus",
ListType(PanelNominationStatusReportDataType),
description = Some("Returns the Employee Reward Report Data"),
arguments = companyIdType :: rewardNamesType :: startDateType :: endDateType :: Nil,
resolve = { c =>
c.ctx.getPanelStatusReport(c.arg(companyIdType), c.arg(startDateType), c.arg(endDateType), c.arg(rewardNamesType))
})
DataRepo:
def getPanelStatusReport(companyId: Int, startDate: Long, endDate: Long, rewardNames: Seq[String]): List[PanelRewardSatusDetail] = {
val redemptionReport = Await.result(reportsModel.findPanelRewardStatusDetailsReport(companyId, rewardNames, startDate, endDate), 20.seconds).toList
redemptionReport
}
And at last the model:
def findPanelRewardStatusDetailsReport(companyId: Int, rewardNames: Seq[String], startDate: Long, endDate: Long): Future[Seq[PanelRewardSatusDetail]] = {
val df = new SimpleDateFormat("dd-MM-yyyy")
val start = stringToDateTime(df.format(startDate * 1000L), None).toDateTime()
val end = stringToDateTime(df.format(endDate * 1000L), None).toDateTime()
val rewardFilter = if(rewardNames.nonEmpty) "AND vrrc.reward_name IN (" + rewardNames.map(a => "'" + a + "'").mkString(",") + ")" else ""
implicit val getOrdersResult = GetResult(r => PanelRewardSatusDetail(r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<, r.<<))
val q = sql"""select vrrc.reward_name, (select login from users where id=vrur.sender_id), (select login from users where id=vrur.receiver_ids), (select city_name from cities where id=(select city_id from users where id=vrur.receiver_ids)), (select login from users where id=approver_user_id), vrur.comment, vrur.business_justification, vrpa.rating, CASE WHEN vrpa.is_approved = 1 THEN 'VOTED' ELSE 'NOT VOTED' END, date(vrpa.created_at), date(vrpa.approved_at) from vr_panel_approval vrpa inner join vr_user_reward vrur on vrur.id=vrpa.user_reward_id inner join vr_reward_config vrrc on vrrc.id=vrur.reward_config_id where vrrc.company_id = $companyId and date(vrpa.created_at) between date($start) and date($end) #$rewardFilter"""
db.run(q.as[PanelRewardSatusDetail])
}
My request query:
{
"query": "query PanelNominationStatus($startDate: Long!, $endDate: Long!, $companyId: Int!, $rewardNames: [String!]!) { PanelNominationStatus( startDate: $startDate, endDate: $endDate, companyId: $companyId, rewardNames: $rewardNames ) { awardName nominatorEmail nomineeEmail nomineeLocation approverEmail citation businessJustification rating votingStatus nominatedDate approvedDate }}",
"operationName": "PanelNominationStatus",
"variables": {
"startDate": 1285891200,
"endDate": 1576108800,
"companyId": 355,
"rewardNames": ["PANEL AWARD FEBRUARY", "PANEL AWARD MARCH"]
}
}
I can make it possible using limit in the query and accepting it in the query but I need to send the total count of rows in the response as well. But I am not able to figure out where to make change in schema.
You just need to define another GraphQL type for your result which also contains the count,
val PanelNominationStatusResultType = ObjectType(
"PanelNominationStatusResult",
"Dashboard Reports",
fields[Unit, List[PanelRewardSatusDetail]](
Field(
"count",
IntType,
description = Some("count of nomination-status-reports in this response"),
resolve = _.value.length
),
Field(
"panelNominationStatusList",
ListType(PanelNominationStatusReportDataType),
description = Some("list of nomination-status-reports"),
resolve = _.value
)
)
)
Now, as for your query,
Field(
"panelNominationStatusResult",
PanelNominationStatusResultType,
description = Some("Returns the details of ............"),
arguments = companyIdType :: rewardNamesType :: startDateType :: endDateType :: Nil,
resolve = { c =>
c.ctx.getPanelStatusReport(c.arg(companyIdType), c.arg(startDateType), c.arg(endDateType), c.arg(rewardNamesType))
}
)
If you want the totalCount, then first of all you need to change your getPanelStatusReport method to also return the totalCount
def findPanelRewardStatusDetailsReport(
companyId: Int,
rewardNames: Seq[String],
startDate: Long,
endDate: Long
): Future[(Int, Seq[PanelRewardSatusDetail])] = ???
// updated result type
val PanelNominationStatusResultType = ObjectType(
"PanelNominationStatusResult",
"Dashboard Reports",
fields[Unit, (Int, List[PanelRewardSatusDetail])](
Field(
"totalCount",
IntType,
description = Some("total count of nomination-status-reports"),
resolve = _.value._1
),
Field(
"count",
IntType,
description = Some("count of nomination-status-reports in this response"),
resolve = _.value._2.length
),
Field(
"panelNominationStatusList",
ListType(PanelNominationStatusReportDataType),
description = Some("list of nomination-status-reports"),
resolve = _.value._2
)
)
)

Mongo DB DAO and Spray JSON :

My Mongo DB abstract Dao is defined as follows
abstract class DbMongoDAO1[K, T <: Keyable[K]] (implicit val manifestT: Manifest[T], val manifestK: Manifest[K])
extends DbDAO[K, T]
with DbDAOExtensions[K, T]
with MongoConnection2
with JsonDbImplicits
{
val thisClass = manifestT.runtimeClass
val simpleName = thisClass.getSimpleName
lazy val collection = db.getCollection(s"${DbMongoDAO1.tablePrefix}$simpleName")
override def insertNew(r:T): Result[String,T] = {
val json: String = r.toJson.compactPrint
collection.insertOne(Document(json))
KO("Not Implemented")
}
}
I'm getting an error in the following line of code when converting a case class to JSON.
Error:(31, 26) value toJson is not a member of type parameter T
val json: String = r.toJson.compactPrint
val json: String = r.toJson.compactPrint
The trait JsonDbImplicits is as follows
trait JsonDbImplicits extends DefaultJsonProtocol
with SprayJsonSupport with JodaImplicits {
implicit val json_UserEmail:RootJsonFormat[UserEmail] = jsonFormat5(UserEmail)
implicit val json_UserProfile:RootJsonFormat[UserProfile] = jsonFormat13(UserProfile)
implicit val json_UserSession:RootJsonFormat[UserSession] = jsonFormat5(UserSession)
}
The case classes UserEmail and UserProfile are defined as follows
case class UserEmail
(
// it is the full email address
#Key("_id") id: String
, account_id: String
, active: Boolean = false
, ts_created: DateTime = now
, ts_updated: DateTime = now
) extends Keyable[String]
trait DbUserEmail extends DbMongoDAO1[String,UserEmail]
and
case class UserProfile
(
// id is the same as AccountId
#Key("_id") id: String = UUID.randomUUID().toString
, gender: Option[String] = None
, first_name: Option[String] = Some("")
, last_name: Option[String] = Some("")
, yob: Option[Int] = None
, kids: Option[Int] = None
, income: Option[Int] = None
, postcode: Option[String] = None
, location: Option[Boolean] = Some(true)
, opt_in: Option[Boolean] = Some(true)
, third_party: Option[Boolean] = Some(true)
, ts_created: DateTime = now
, ts_updated: DateTime = now
) extends Keyable[String]
trait DbUserProfile extends DbMongoDAO1[String,UserProfile]
What am I missing?

Json data in an object

I would like put the json data in a object in opa.
I saw a comment ( parsing a webclient.Result content in OPA ) which describes how to do that but I tried that approach and can't make it work with my application.
Here's my code :
type service = {
string name,
string kind,
string vendor
}
contentResult = WebClient.Get.try_get(url);
match(contentResult)
{
case { failure : _ }: "Error, could not connect";
case ~{success}:
match (Json.deserialize(success.content)){
case {none}: "Error the string doesn't respect json specification";
case {some:jsast}: match (OpaSerialize.Json.unserialize_unsorted(jsast)){
case {none}: "The type 'result' doesn't match jsast";
case {some =(value:service)}: value.name;
}
}
}
I want to create an object of type service with the data from the json file.
The last match seems to be a problem because it displays in output
The type 'result' doesn't match jsast
In fact, i have more keys in my json file than this 3 above, here my log:
X Data: [
{
"name": "redis-d80d7",
"type": "key-value",
"vendor": "redis",
"version": "2.2",
"tier": "free",
"properties": {},
"meta": {
"created": 1310772000,
"updated": 1310772000,
"tags": [
"redis",
"redis-2.2",
"key-value",
"nosql"
],
"version": 1
}
},
JsAST: {List = [{Record = [{f1 = name; f2 = {String = redis-d80d7}},
{f1 = type; f2 = {String = key-value}}, {f1 = vendor; f2 = {String = redis}},
{f1 = version; f2 = {String = 2.2}}, {f1 = tier; f2 = {String = free}},
{f1 = properties; f2 = {Record = []}}, {f1 = meta; f2 = {Record =
[{f1 = created; f2 = {Int = 1310772000}}, {f1 = updated;
f2 = {Int = 1310772000}}, {f1 = tags; f2 = {List = [{String = redis},
{String = redis-2.2}, {String = key-value}, {String = nosql}]}},
{f1 = version; f2 = {Int = 1}}]}}]}